Hallo,
ich versuche momentan meine ersten Schritte in Hibernate zumachen und hab mir zu diesem Zweck mal ein 3-teiliges Videotutorial zu Hibernate angeschaut. War alles in allem echt nett gemacht und erweckte in mir den Eindruck, dass ich mit dem Gerlernten recht schnell den Dreh raushaben sollte. Leider lief mir heute ein Problem über den Weg, welches ich bisher nicht so wirklich beheben konnte.
Hier mal meine Entitys:
Und hier meine DAOs:
Nun habe ich mir mal ne Klasse zum Testen meiner Funktionen gemacht und folgendes probiert:
Leider bekomme ich dann folgende Exception beim Ausführen der Zeile
.
Mir ist schon klar, dass das wohl daran liegt, dass er beim Lazy-Fetchen der Liste nicht mehr die gleiche Session nutzt, die er beim eigentlichen Holen des User-Objekts genutzt hat. Beim Googlen bin ich dann darauf gestoßen, dass man die Session wohl mit session.load() wiederbekommt, wie man in der Funktion
in der UserDAO sehen kann. Funktioniert nur leider nicht wie erhofft. Auch das Umstellen des FetchTypes auf Eager hat nicht zum gewünschten Ergebnis geführt und ich denke es muss ja auch mit dem Performance-schonenden Lazy-Loading gehen.
Ist mein genereller Ansatz mit den Sessions falsch? Wenn ja, wie löst man das besser?
Schöne Grüße,
Patrick
ich versuche momentan meine ersten Schritte in Hibernate zumachen und hab mir zu diesem Zweck mal ein 3-teiliges Videotutorial zu Hibernate angeschaut. War alles in allem echt nett gemacht und erweckte in mir den Eindruck, dass ich mit dem Gerlernten recht schnell den Dreh raushaben sollte. Leider lief mir heute ein Problem über den Weg, welches ich bisher nicht so wirklich beheben konnte.
Hier mal meine Entitys:
Java:
@Entity
public class User implements Serializable {
@Id
@Column(name="User_ID")
@GeneratedValue
private Long Id;
private String name;
private String pw;
private String email;
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
private Collection<Driver> drivers = new ArrayList<Driver>();
public User() {
}
public User(String name, String pw, String email) {
this.name = name;
this.pw = pw;
this.email = email;
}
public Long getId() {
return Id;
}
public void setId(Long Id) {
this.Id = Id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPw() {
return pw;
}
public void setPw(String pw) {
this.pw = pw;
}
public Collection<Driver> getDrivers() {
return drivers;
}
public void setDrivers(Collection<Driver> drivers) {
this.drivers = drivers;
}
}
@Entity
public class Driver implements Serializable {
@Id
@GeneratedValue
private Long Id;
private Team team;
private Championship cs;
public Driver() {
}
public Driver(Team team, Championship cs) {
this.team = team;
this.cs = cs;
}
public Long getId() {
return Id;
}
public void setId(Long Id) {
this.Id = Id;
}
public Championship getCs() {
return cs;
}
public void setCs(Championship cs) {
this.cs = cs;
}
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
}
Und hier meine DAOs:
Java:
public class UserDAO {
public void addUser(User u) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
session.save(u);
transaction.commit();
}
public void updatePassword(User u, String newPW) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
u.setPw(newPW);
session.saveOrUpdate(u);
transaction.commit();
}
/*
* returns either the user with the given name or null if no user with this
* name exists
*/
public User getUserByName(String name) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from User where name = :name");
query.setParameter("name", name);
List resultList = query.list();
if (resultList.size() > 0) {
transaction.commit();
return (User) resultList.listIterator().next();
} else {
transaction.commit();
return null;
}
}
public User getUserById(Long Id) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
User u = (User) session.get(User.class, Id);
transaction.commit();
return u;
}
public void deleteUserById(Long Id) {
User delUser = getUserById(Id);
if (delUser != null) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
session.delete(delUser);
transaction.commit();
}
}
public List<User> getUsers() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from User");
return query.list();
}
public void addDriver(User u, Driver d) {
DriverDAO driverDAO = new DriverDAO();
driverDAO.addDriver(d);
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
u.getDrivers().add(d);
transaction.commit();
}
public List<Driver> getDrivers(User u) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.load(User.class, u.getId());
Transaction transaction = session.beginTransaction();
List<Driver> drivers = (List<Driver>) u.getDrivers();
return drivers;
}
}
public class DriverDAO {
public void addDriver(Driver d) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
session.save(d);
transaction.commit();
}
}
Nun habe ich mir mal ne Klasse zum Testen meiner Funktionen gemacht und folgendes probiert:
Java:
public static void main(String[] args) {
User patrick = new User("Patrick", "test123", "thepadde86@googlemail.com");
UserDAO userDAO = new UserDAO();
userDAO.addUser(patrick);
userDAO.addUser(dieter);
userDAO.addUser(falko);
userDAO.addDriver(patrick, new Driver(new Team(), new Championship()));
userDAO.addDriver(patrick, new Driver(new Team(), new Championship()));
userDAO.addDriver(patrick, new Driver(new Team(), new Championship()));
userDAO.addDriver(patrick, new Driver(new Team(), new Championship()));
User temp = userDAO.getUserByName("Patrick");
List<Driver> listOfDrivers = userDAO.getDrivers(temp);
for (Driver driver : listOfDrivers) {
System.out.println("Driver: " + driver.getId());
}
}
Leider bekomme ich dann folgende Exception beim Ausführen der Zeile
Code:
List<Driver> listOfDrivers = userDAO.getDrivers(temp);
Code:
Schwerwiegend: failed to lazily initialize a collection of role: de.racegatherer.classes.User.drivers, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: de.racegatherer.classes.User.drivers, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:249)
at de.racegatherer.RaceGathererDB.main(RaceGathererDB.java:41)
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: de.racegatherer.classes.User.drivers, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:249)
at de.racegatherer.RaceGathererDB.main(RaceGathererDB.java:41)
Mir ist schon klar, dass das wohl daran liegt, dass er beim Lazy-Fetchen der Liste nicht mehr die gleiche Session nutzt, die er beim eigentlichen Holen des User-Objekts genutzt hat. Beim Googlen bin ich dann darauf gestoßen, dass man die Session wohl mit session.load() wiederbekommt, wie man in der Funktion
Code:
public List<Driver> getDrivers(User u)
Ist mein genereller Ansatz mit den Sessions falsch? Wenn ja, wie löst man das besser?
Schöne Grüße,
Patrick