Hibernate Anfänger Problem

G

Guest123

Hallo zusammen,
ich arbeite mich gerade in Hibernate ein, und versuche mich momentan an einer bidirektionalen many-to-one Beziehung.
Das Mapping selbst klappt, nur das Select funktioniert nicht wie gewünscht.
Die beiden Klassen, etwas vereinfacht, sehen so aus:

Java:
@Entity
@Table(name="ADMIN_GROUP")
public class Group extends DBObject{
	@OneToMany(mappedBy="group")
	private List<User> userList;
	
	
	public Group(){
		super();
	}
        public List<User> getUserList() {
		return userList;
	}


	public void setUserList(List<User> userList) {
		this.userList = userList;
	}
	
}
Java:
@Entity
@Table(name="ADMIN_USER")
public class User extends DBObject{
	@ManyToOne
	@JoinColumn(name="groupID", nullable = false)
	private Group group;
	
	public User(){
		super();
	}


	public void setGroup(Group group) {
		this.group = group;
	}




	public Group getGroup() {
		return group;
	}	
	
}
Und noch die Basisklasse:
Java:
@Entity
@Table(name="ADMIN_OBJECT")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class DBObject{
	@Column(length = 255, nullable = false)
	private String name;
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE)
	private Long id;
	@Column(length=1024)
	private String description;
	@Column(nullable = false)
	@Version
	private Long version;
	
	
	public DBObject(){
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public  Long getId(){
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public Long getVersion() {
		return version;
	}
	public void setVersion(Long version) {
		this.version = version;
	}
	
	
	
	
	
}

Der Aufruf sieht dann so aus:
Java:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		session.save(org);
		session.flush();
		
		Group g = new Group();
		
		
		
		User user = new User();
		user.setGroup(g);
		
		session.save(g);
		session.save(user);
		
		
		User user2 = new User();
		user2.setGroup(g);
		session.save(user2);
		
		
		session.save(g);
		
		session.flush();
		//1
		List<Group> groupList = session.createQuery("from Group as group").list();
		for(Group group: groupList){
			System.out.println(group);
		}
                //2
                List<User> userList = session.createQuery("from User as user").list();
		for(User u: userList){
			System.out.println(u);
		}
		
		//System.out.println(g);
		//System.out.println(g.getUser());
                session.commit();

Gespeichert wird alle richtig. Auch die Abfrage 2 wird korrekt ausgeführt. Die selektierten User Objekte haben auch alle ein Gruppen Objekt. Bei der Abfrage (1) nach den Gruppen ist das Feld "userList" der Gruppen Objekte leider leer.
Hat jemand eine Idee, was ich falsch mache?

*gruß*
Sebastian
 
Hallo Sebastian,

Ohne es auszuprobieren fällt mir auf, dass Du beim Speichern lediglich den Usern die Gruppe zuordnest, aber nicht der Gruppe die User hinzufügst.

Bei bidirektionalen Beziehungen müssen im Objektnetz beide an einer Beziehung beteiligten Seiten auf das Objekt der anderen Seite verweisen.

Code:
Group g = new Group();
ArrayList<User> userList = new ArrayList<User>();
g.setUserList(userList);

User user = new User();
user.setGroup(g);
g.getUserList().add(user);
        
session.save(g);
session.save(user);

Gruß
Alexander
 
Hi Alexander,
danke für die Antwort.
Ist sehr umständlich, aber hast leider recht mit deiner Antwort.
Was aber funktioniert: Wenn ich auf der Transaktion ein commit aufrufe und dann erst die Gruppe lade, funktioniert alles wie gewollt.
Auch nicht sonderlich schön, oder kann man dies erventuell noch mit zusätzlichen Konfigurationsparametern beinflussen?

*gruß*
Sebastian
 
Hallo Sebastian,

Ich versuche Dir einen aus meiner Sicht grundsätzlichen Denkfehler aufzuklären.

Es gibt eine relationale Welt der Datenbank und es gibt eine objektorientierte Welt im Arbeitsspeicher. Hibernate vermittelt zwischen den Welten auf Basis von einer Menge Regeln. Es liegt in der Verantwortung des Programmierers, darauf zu achten, dass die objektorientierte Welt richtig programmiert ist, und dass der Programmierer die Mappings im Rahmen der gegebenen Möglichkeiten richtig macht. Wenn dort irgendwas falsch ist, kommt es zu komischen Effekten.

Über den komischen Effekt, den Du beobachtest, stolpert jeder, der mit Hibernat bzw. JPA beginnt. Die Ursache liegt nicht in einer "Umständlichkeit" oder falschen Konfiguration. Dass Hibernate die lückenhaft verdrahteten Objekte trotzdem richtig speichert ist allein kein Beweis für eine korrekte Programmierung.

Wäre Hibernate nicht im Spiel wäre, wäre Deine Verdrahtung der Objekte trotzdem falsch. Auch ohne Hibernate muss eine bidirektionale Beziehung zwischen den Objekten vollständig und nicht nur einseitig bedient werden! Dasselbe gilt natürlich auch für das Entfernen von Objekten aus bidirektionalen Beziehungen.

Die Beziehung wird weniger umständlich, wenn Du sie unidirektional anstatt bidirektional gestaltest.

Gruß
Alexander
 

Neue Beiträge

Zurück