Hibernate : No identifier specified for entity - java

I've developed a simple web application which connects to MySQL through hibernate. At a point, I was even successful in creating a connection and inserting the java object in the DB. However, I did some changes thereafter to meet my project needs and there I messed up the things. I am receiving this error "No identifier specified for entity" no matter how much I try to debug it. I even created a new project from scratch but in vain. Please help me out here in identifying what I am doing wrong.
package com.proj.beandb;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
#ManagedBean
#SessionScoped
#Entity
#Table(name="dbstat")
public class Hibernate
{
#Id
#Column(name="first_name")
private static String fname;
#Column(name="last_name")
private static String lname;
public Hibernate(){}
public Hibernate(String fname, String lname)
{
Hibernate.fname = fname;
Hibernate.lname = lname;
}
public static void main(String[] args) {
// create session factory
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml")
.addAnnotatedClass(Student.class)
.buildSessionFactory();
// create session
Session session = factory.getCurrentSession();
try {
// create a student object
System.out.println("Creating new object");
Hibernate tempRec = new Hibernate("bah", "blah");
// start a transaction
session.beginTransaction();
// save the object
session.save(tempRec);
// commit transaction
session.getTransaction().commit();
System.out.println("Done!");
}
finally {
factory.close();
}
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
Hibernate.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
Hibernate.lname = lname;
}
}
`

It is a really a big mistake to use static fields as properties of a persistent class.
#Id
#Column(name="first_name")
private static String fname;
#Column(name="last_name")
private static String lname;
should be
#Id
#Column(name="first_name")
private String fname;
#Column(name="last_name")
private String lname;
You don't need it, because of it is not a Hibernate related stuff
#ManagedBean
#SessionScoped
You add Student class with addAnnotatedClass(Student.class), maybe you need to add Hibernate class instead.
And please don't put main() in the persistent class. You need to have Hibernate class and, for an example, HibernateTest class with main().

Related

Hibernate Error : attempted to assign id from null one-to-one property. Why?

I am trying my hands at Hibernate Relation Mapping(OneToOne, etc) exercises using Spring Boot. Before you ask, I have already consulted this link : [https://stackoverflow.com/questions/11104897/hibernate-attempted-to-assign-id-from-null-one-to-one-property-employee]. I understand that the weak entity needs to have a ref to the parent entity, but I am not able to figure out, why I need to do that explicitly in Person class constructor?
The Codes are as follows.
SpringApplication:
package com.OneToOne.OneToOneMappingPractice;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class App
{
public static void main( String[] args )
{
ApplicationContext applContext = SpringApplication.run(App.class, args);
String[] beanNames = applContext.getBeanDefinitionNames();
Arrays.sort(beanNames);
for(String beanName : beanNames)
System.out.println(beanName);
}
}
CRUDController.java:
package com.OneToOne.OneToOneMappingPractice;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#CrossOrigin
public class CRUDController
{
private static int randomNumber=(int) Math.random();
#Autowired
private CRUDControllerRepository repository;
#GetMapping(value="/add")
public void add()
{
Person person = new Person("Person"+randomNumber, "Street"+randomNumber, randomNumber);
repository.save(person);
randomNumber+=1;
}
#GetMapping(value="/getAll")
public List<Person> getAll()
{
return repository.findAll();
}
#DeleteMapping(value="/deleteAll")
public void deleteAll()
{
repository.deleteAll();
}
}
Person.java:
package com.OneToOne.OneToOneMappingPractice;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
#Entity
public class Person
{
private String name;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private int Id;
#OneToOne(mappedBy="person", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private Address address;
public Person() {}
public Person(String name, String streetName, int house_number)
{
super();
this.name = name;
this.address=new Address();
this.address.setStreetName(streetName);
this.address.setHouse_number(house_number);
//this.address.setPerson(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
Address.java:
package com.OneToOne.OneToOneMappingPractice;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
#Entity
public class Address {
#Id
#Column(name="user_id")
private int Id;
private int house_number;
private String streetName;
#OneToOne
#MapsId
#JoinColumn(name = "user_id")
private Person person;
public Address(){}
public int getHouse_number() {
return house_number;
}
public void setHouse_number(int house_number) {
this.house_number = house_number;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
// public Person getPerson() {
// return person;
// }
public void setPerson(Person person) {
this.person = person;
}
}
CRUDControllerRepository.java:
package com.OneToOne.OneToOneMappingPractice;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
#Repository
#Transactional
public interface CRUDControllerRepository extends JpaRepository<Person, Integer>
{
Person save(Person person);
void deleteAll();
List<Person> findAll();
}
Following are my questions :
As you can see, in the Person class parameterized constructor, I have commented out the line : this.address.setPerson(this);. If I keep this line commented out, I get the exception : "attempted to assign id from null one-to-one property [com.OneToOne.OneToOneMappingPractice.Address.person]; nested exception is org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [com.OneToOne.OneToOneMappingPractice.Address.person]". If I remove the comment syntax, it works perfectly. Why do I need to explicitly do this? Isn't the #OneToOne annotation supposed to take care of these references by itself?
2.If I enable the Person getPerson() method in the Address class, it recursively goes on, until the stack explodes: "Cannot render error page for request [/getAll] and exception [Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException".
Why cant Hibernate itself determine that it needs to stop at that boundary itself, instead of fetching the Parent Object again?
Am I missing something here about these mapping annotations, or anything else?
1- As you can see, in the Person class parameterized constructor, I
have commented out the line : this.address.setPerson(this);. If I keep
this line commented out, I get the exception : "attempted to assign id
from null one-to-one property
Hibernate will not set it explicitly because it does not know to which person this address belongs to you need to specify that explicitly.
The purpose of #OneToOne is to tell hibernate where to get the rest of the data when it is already mapped.
2.If I enable the Person getPerson() method in the Address class, it recursively goes on, until the stack explodes: "Cannot render error
page for request [/getAll] and exception [Could not write JSON:
Infinite recursion (StackOverflowError); nested exception is
com.fasterxml.jackson.databind.JsonMappingException". Why cant
Hibernate itself determine that it needs to stop at that boundary
itself, instead of fetching the Parent Object again?
The exception is caused by Jackson serializer and not from hibernate.
you can look at the examples here to see how it is fixed https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion.

save working but persist not working in hibernate 4.1.1

I am trying to save data usign hsqldb and I am using hibernate 4.1.4.Final. My problem is I want to save data using persist but when I tried to do it's showing following error:
org.hibernate.PersistentObjectException: detached entity passed to persist: main.java.entity.Advocate
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:835)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:828)
at org.hibernate.engine.spi.CascadingAction$7.cascade(CascadingAction.java:315)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:844)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:819)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:823)
at main.java.service.LegalService.registerCase(LegalService.java:46)
at main.java.tester.Tester.registerCase(Tester.java:52)
at main.java.tester.Tester.main(Tester.java:28)
But when I use save method it worked.So I want to know how persist and save makes difference? and my entity classes are serialized.How to solve this persist error.
Here is my class
package main.java.service;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import main.java.businessTier.CaseTO;
import main.java.entity.Advocate;
import main.java.entity.Case;
public class LegalService {
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(
configuration.getProperties()). buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
public int registerCase(CaseTO caseTO) {
try
{
Session session;
session=sessionFactory.openSession();
session.beginTransaction();
Case c = new Case();
Advocate a = new Advocate();
a.setAdvocateId(caseTO.getAdvocateId());
c.setAdvocate(a);
c.setClientAge(caseTO.getClientAge());
c.setClientName(caseTO.getClientName());
c.setDate(caseTO.getDate());
c.setDescription(caseTO.getDescription());
session.persist(c);
session.getTransaction().commit();
return c.getCaseNo();
}
catch(Exception e){
e.printStackTrace();
return 0;
}
}
}
Here are my entity class
Advocate.java
package main.java.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
#Entity
#Table(name="Db_Advocate")
#DynamicInsert(value=true)
#DynamicUpdate(value=true)
public class Advocate {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="advocateId")
private Integer advocateId;
#Column(name="name")
private String name;
#Column(name="age")
private Integer age;
#Column(name="category")
private String category;
#Column(name="court")
private String court;
#Column(name="city")
private String city;
public Integer getAdvocateId() {
return advocateId;
}
public void setAdvocateId(Integer advocateId) {
this.advocateId = advocateId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getCourt() {
return court;
}
public void setCourt(String court) {
this.court = court;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
Case.java
package main.java.entity;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
#Entity
#Table(name="DB_CASE")
#DynamicInsert(value=true)
#DynamicUpdate(value=true)
public class Case {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer caseNo;
#JoinColumn(name="advocateId")
#ManyToOne(cascade=CascadeType.ALL)
private Advocate advocate;
private String clientName;
private Integer clientAge;
private String description;
private Date date;
public Integer getCaseNo() {
return caseNo;
}
#Column(name="caseNo")
public void setCaseNo(Integer caseNo) {
this.caseNo = caseNo;
}
public Advocate getAdvocate() {
return advocate;
}
public void setAdvocate(Advocate advocateId) {
this.advocate = advocateId;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public Integer getClientAge() {
return clientAge;
}
public void setClientAge(Integer clientAge) {
this.clientAge = clientAge;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDate() {
return date;
}
#Column(name="data",nullable=true)
public void setDate(Date date) {
this.date = date;
}
}
First you need to understand behaviour of persist().
Below are the links that will help you understand the behaviour
Whats the difference between persist() and save() in Hibernate?
http://javarevisited.blogspot.in/2012/09/difference-hibernate-save-vs-persist-and-saveOrUpdate.html
Now in order to solve this problem in your code .. use merge() instead of persist().
Why persist() gave the exception
persist() does not work for detached objects .You need to know how hibernate determines whether an object is detached or not.
UPDATE
Why the identifier generation strategy auto solved your problem
As i mentioned above that you need to understand the rules by which hibernate identifies whether an object is detached or transient. Below are the rule
If the the entity has a null value for identifier or the version attribute is null it is considered as transient other wise detached.
If you use auto-generated identifiers, and the identifier is not null, then Hibernate considers it as a detached entity.
If you are using assigned identifier strategy then hibernate will issue a fetch to determine whether the identifier exists in db based on that your entity will be either transient or detached.
Now that being said .. we analyse your code.
In your code you have Advocate entity whose identifier strategy is IDENTITY.In the below code
Case c = new Case();
Advocate a = new Advocate();
a.setAdvocateId(caseTO.getAdvocateId());
You are setting the identifier property of Advocate instance manually.At the time of flush when transaction commits ,hibernate will see that the identifier generation strategy is IDENTITY and the identifier value is set in the advocate instance hence it will conclude that the entity instance is detached (this is from the rule 1 described above).And hence the persist() method gave exception for the advocate instance as it is deemed to be detached from hibernate.
From rule 2 we can say that your code will not work just by changing the generation strategy to auto.You might have done some other changes.
I have tried your code on my system it is giving the same exception even if i change the generation strategy to auto which is in consistent with the rules
You might be doing something different in your code .. please check and update.
Please also post the identifier that you are setting in the advocate and the actual identifier generated for that advocate in database with auto generation strategy, that might be helpful
Please Add below code at id
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Then persist will work

Value getting over ridden in DB

Please help me here. I am new to Hibernate. Done the setup successfully. But when I run the code with different values, the values in the table are getting over written. I've no idea what is going wrong. Here is my code:
UserDetails.java
package com.hibernate;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="User_Details")
public class UserDetails {
#Id
private int id;
private String name;
private String phonenumber;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhonenumber() {
return phonenumber;
}
public void setPhonenumber(String phonenumber) {
this.phonenumber = phonenumber;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
GetUserDetails.java
package com.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
#SuppressWarnings("deprecation")
public class GetUserDetails {
public static void main(String[] args) {
UserDetails ud = new UserDetails();
ud.setId(3);
ud.setName("User3");
ud.setPhonenumber("9988555774");
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(ud);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
When I run the above code, with the values "3", "User3", "9988555774" is getting inserted into the table.
But if I run the code again with the values "4", "User4", "9988547774", then the old value is getting over written and the new values are inserted correctly.
Please help me as I don't know what I'm missing.
I beleive you've added the following line in your hibernate.cfg.xml.
<property name="hbm2ddl.auto">create</property>
Try changing "create" to "update", as shown below:
<property name="hbm2ddl.auto">update</property>
Refer the following link for more info about the above property values:
Hibernate hbm2ddl.auto possible values and what they do?
Hibernate: hbm2ddl.auto=update in production?

retrieve data of collection type from database using getters and setters

i am having three classes one is USER, second Vehicle and third is notfound_test.
In USER class i declared vehicle as Collection as follow.
Collection vehicle=new ArrayList();
And also having getters and setters of it.
So, my question is how i can retrieve data from database i am using hibernate?
I tried following code.
i am unable from getting data in JOPTIONPANE OF VEHICLE IN THIRD CLASS.i wanted the associated data
package org.notfound.annotation;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity
public class User {
#Id #GeneratedValue
private int id;
private String name;
#OneToMany
Collection<Vehicle> vehicle=new ArrayList<Vehicle>();
public Collection<Vehicle> getVehicle() {
return vehicle;
}
public void setVehicle(Collection<Vehicle> vehicle) {
this.vehicle = vehicle;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package org.notfound.annotation;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
#Entity
public class Vehicle {
#Id #GeneratedValue
private int vehicle_id;
private String vehicle_name;
#ManyToOne
private User user=new User();
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public int getVehicle_id() {
return vehicle_id;
}
public void setVehicle_id(int vehicle_id) {
this.vehicle_id = vehicle_id;
}
public String getVehicle_name() {
return vehicle_name;
}
public void setVehicle_name(String vehicle_name) {
this.vehicle_name = vehicle_name;
}
}
package org.notfound.annotation;
import javax.swing.JOptionPane;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Notfound_test {
public static void main(String[] args) {
User user=new User();
Vehicle vehicle=new Vehicle();
Vehicle vehicle2=new Vehicle();
user.setName("NIRAV J. KAMANI");
vehicle.setVehicle_name("CHEVROLET CRUIZE");
vehicle2.setVehicle_name("MARUTI ERTIGA");
vehicle.setUser(user);
vehicle2.setUser(user);
user.getVehicle().add(vehicle);
user.getVehicle().add(vehicle2);
SessionFactory sessionfactory=new Configuration().configure().buildSessionFactory();
Session session=sessionfactory.openSession();
/*session.beginTransaction();
session.save(user);
session.save(vehicle);
session.save(vehicle2);
session.getTransaction().commit();
session.close();*/
session.beginTransaction();
user=(User) session.get(User.class, 1);
vehicle=(Vehicle) session.get(Vehicle.class, 1);
vehicle2=(Vehicle) session.get(Vehicle.class, 2);
JOptionPane.showMessageDialog(null, user.getId()+" "+user.getName()+" "+user.getVehicle().toString(), "INFORMATION", JOptionPane.INFORMATION_MESSAGE);
session.close();
}
}
As always, you forgot the mappedBy annotation on the OneToMany. It's a bidirectional OneToMany association, and the one side must thus be the inverse side of the many side, as explained in the documentation:
#OneToMany(mappedBy = "user")
private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();
I also renamed the fields to vehicles, since it's a collection, and thus contains several ones.
EDIT:
Your comment shows that the 2 vehicles are printed:
[org.notfound.annotation.Vehicle#37ed25, org.notfound.annotation.Vehicle#aec63]
^-- first vehicle ^-- second vehicle
^-- brackets, indicating that it's a collection ------------------------------^
If you want them to be printed is a different way than the dafult way, you need to override the toString() method in vehicle, as for any Java object.

How to avoid LazyInitializationException in Hibernate?

I am using Hibernate as the ORM for a database that has a number of foreign key relationships. The problem is that sometimes I want to fetch these related datasets and sometimes I do not, so on these collections I have set "fetch" to "lazy". Unfortunately, every time I try to serialize these objects Hibernate will throw a LazyInitializationException, because the session is closed. Using an OpenSessionInView filter simply causes Hibernate to populate these collections anyway, thus defeating the whole purpose of having a lazy collection in the first place.
Is there a simple way to serialize or otherwise extract the data populated in the POJO without triggering the LIE, and without having to populate all of the lazy collections?
EDIT: Here is some example code I am trying to get working, dealing with two tables, "Departments" and "Employees," which is the child in a one-to-many relationship with Departments. I want to be able to view the Departments listed in the database, without having to load all of the Employees that belong to said Departments:
Departments:
package com.test.model;
// Generated Apr 7, 2012 7:10:28 PM by Hibernate Tools 3.4.0.CR1
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* Departments generated by hbm2java
*/
#Entity
#Table(name="Departments"
,catalog="test"
)
public class Departments implements java.io.Serializable {
private Integer id;
private String name;
private Set<Employees> employeeses = new HashSet(0);
public Departments() {
}
public Departments(String name) {
this.name = name;
}
public Departments(String name, Set employeeses) {
this.name = name;
this.employeeses = employeeses;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="Id", unique=true, nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name="Name", nullable=false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch=FetchType.LAZY, mappedBy="departments")
public Set<Employees> getEmployeeses() {
return this.employeeses;
}
public void setEmployeeses(Set employeeses) {
this.employeeses = employeeses;
}
}
Employees:
package com.test.model;
// Generated Apr 7, 2012 7:10:28 PM by Hibernate Tools 3.4.0.CR1
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* Employees generated by hbm2java
*/
#Entity
#Table(name="Employees"
,catalog="test"
)
public class Employees implements java.io.Serializable {
private Integer id;
private Departments departments;
private String firstName;
private String lastName;
public Employees() {
}
public Employees(Departments departments, String firstName, String lastName) {
this.departments = departments;
this.firstName = firstName;
this.lastName = lastName;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="Id", unique=true, nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="DepartmentsId", nullable=false)
public Departments getDepartments() {
return this.departments;
}
public void setDepartments(Departments departments) {
this.departments = departments;
}
#Column(name="FirstName", nullable=false)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name="LastName", nullable=false)
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
My action class (which gets serialized by the Struts2 XSLT result):
package com.test.view;
import java.util.List;
import java.util.Iterator;
import com.opensymphony.xwork2.ActionSupport;
import com.test.controller.DepartmentsManager;
import com.test.model.Departments;
import com.test.util.HibernateUtil;
public class DepartmentsAction extends ActionSupport {
private DepartmentsManager departmentsManager;
private List<Departments> departmentsList;
public DepartmentsAction() {
this.departmentsManager = new DepartmentsManager();
}
public String list() {
this.departmentsList = departmentsManager.list();
System.out.println("Execute called");
HibernateUtil.createDTO(departmentsList);
return SUCCESS;
}
public List<Departments> getDepartmentsList() {
return departmentsList;
}
public void setDepartmentsList(List<Departments> departmentsList) {
this.departmentsList = departmentsList;
}
}
My Manager class (which the Action class calls to populate the list of Departments):
package com.test.controller;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import com.test.model.Departments;
import com.test.util.HibernateUtil;
public class DepartmentsManager {
public List<Departments> list() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<Departments> set = null;
try {
Query q = session.createQuery("FROM Departments");
/*Query q = session.createQuery("FROM Departments d JOIN FETCH d.employeeses e");*/
q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
set = (List<Departments>) q.list();
} catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
}
session.getTransaction().commit();
return set;
}
}
Lazy collections work only within the scope of the transaction (where the owning entity was retrieved from a DB). In other words, you should not pass a Hibernate entity with non-loaded lazy sub-entities or collections outside the transaction scope.
You need either to build another entity or use lazy="false" if you want to pass an entity to JSP, or serialization code or anything else.
Two simple ways to manage lazy loading within view :
Using a Transaction view (consisting in wrapping view calls into JTA transaction (application-managed for instance)
Using an extented persistence context in your bean and flushing it explicitely when you've done with it, that means as soon as you were able to load your lazy objects.
For more information, check this post and the answer that belongs to it:
JPA lazy loading Collections in JSF view - better way than using Filters?

Categories