-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: "equality" vs. "identity": Kann Hibernat
PostPosted: Sat Feb 17, 2007 1:31 pm 
Newbie

Joined: Sat Feb 17, 2007 12:37 pm
Posts: 1
Hallo,

Ich nutze Hibernate 3.2 mit den Annotations gegen ein MySQL-Backend und habe gerade so ein kleines konzeptionelles Problem beim Persistieren eines vorgegebenen Models. Mein Problem ist, dass in dem Model gleiche Objekte existieren ("Equality" in Bezug auf die gesetzten Attribute), die jedoch eine unterschiedliche Identität besitzen (es sind halt leider unterschiedliche Java Objekte).

Gibt es eine Möglichkeit diese "Konflikte" hibernateseitig beim Persistieren zu beseitigen, sodass alle gleichen Objekte auf den gleichen Datensatz in der Datenbank abgelegt werden und das Objekt dann nicht mehrfach exisitiert?

Innerhalb der Klassen sind die .equals() und .hashcode() Methoden soweit korrekt implementiert, die gleichen Objekte werden also als gleich erkannt.

Wenn ich in den Klassen für die ID ein @GeneratedValue angebe, werden die Objekte mehrfach abgelegt, weil jedes Objekt eine eigene ID bekommt. Ich habe bereits versucht den ID-Generator für die Objekte so zu bauen, dass gleiche Objekte auch den gleichen Identifier "abbekommen", jedoch beschwert sich Hibernate dann, dass in der Session unterschiedlichen Objekten gleiche IDs vergeben wurden.

Am saubersten wäre es wohl, direkt im Parser die Korrekturen hierfür anzusetzen, jedoch kann ich am Parser nichts ändern, da der mir geliefert wird. Einzige Möglichkeit, die mir so adhoc noch einfällt, wäre eine "repair" Funktion, die über das komplette Model läuft und auf solche Mehrfacheinträge checkt, ich fände es aber wesentlich sauberer, wenn Hibernate mir das irgendwie abnehmen könnte.

Ich bin noch relativ neu in der Thematik "Persistierung mit Hibernate" und würde mich freuen, wenn mir jemand ein paar Hinweise zu meinem Problem geben könnte, oder zumindest einen weiterführenden Link ins Forum / Doku / Buch, wo es weitere Informationen zu dieser Thematik gibt.

Vielen Dank für die Mühe!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 22, 2007 7:55 am 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
a)
vor dem Speichern mit session.get prüfen, ob das Objekt schon da ist.
b)
Composite ID verwenden (annotations idclass oder embeddedid)

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 25, 2007 1:57 pm 
Newbie

Joined: Sun Feb 25, 2007 1:35 pm
Posts: 5
Ich habe genau das gleiche Problem und habe nach deinem Hinweis folgenden Code benutzt, um das Ganze zu lösen:

Klasse Person:
Code:
@Entity
@Embeddable
public class Person {
   private Long id;
   private int age;
   private String firstname;
   private String lastname;

   @GeneratedValue
   public Long getId() {
      return id;
   }
   
   @SuppressWarnings("unused")
   private void setId(Long id) {
      this.id = id;
   }

   @Id
   public int getAge() {
      return age;
   }
   
   public void setAge(int age) {
      this.age = age;
   }

   @Column(length=30)
   @Id
   public String getFirstname() {
      return firstname;
   }
   
   public void setFirstname(String firstname) {
      this.firstname = firstname;
   }

   @Id
   public String getLastname() {
      return lastname;
   }
   
   public void setLastname(String lastname) {
      this.lastname = lastname;
   }

   private Person() {
      firstname = "foo";
      lastname = "bar";
      age = 0;
   }
   
   public Person(String firstName, String lastName, int age) {
      this();
      this.firstname = firstName;
      this.lastname = lastName;
      this.age = age;
   }

   @Override
   public boolean equals(Object object) {
      if (object instanceof Person) {
         Person otherPerson = (Person) object;
         
         return
            firstname.equals(otherPerson.getFirstname()) &&
            lastname.equals(otherPerson.getLastname()) &&
            (age == otherPerson.getAge());
      }
      return false;
   }

   @Override
   public int hashCode() {
      return (firstname + lastname + age).hashCode();
   }
}


Ich habe also eine ID über firstName, lastName und age generiert. Alelrdings bekomme ich beim Einfügen folgende Exception
Code:
Exception in thread "main" org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
   at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
   at events.EventManager.main(EventManager.java:40)
Caused by: java.sql.BatchUpdateException: Field 'lastname' doesn't have a default value
   at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:665)
   at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
   ... 8 more

Gibt es in Hibernate einen Weg, dieses Problem zu umgehen bzw. einen Default-Wert für eine Spalte anzugeben.
Wie im Konstruktor zu sehen habe ich die Variable lastName initialisiert, was jedoch den oben genannten Fehler nicht behebt.

Danke für euere Hilfe.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 26, 2007 2:01 am 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
Der leere Konstruktor sollte nicht privat sein, wenn er benutzt werden soll. Ich würde als Default Values lieber leere Strings verwenden und Hibernate auch so konfigurieren, dass diese als nicht initialisiert wahrgenommen werden. (-> unsigned)

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 26, 2007 11:30 am 
Newbie

Joined: Sun Feb 25, 2007 1:35 pm
Posts: 5
Hallo Sebastian,

vielen Dank für deine Hilfe.
Ich habe gerade Mal deinen Hinweis wegen des privaten Konstruktors ausprobiert aber es kommt weiterhin die oben erwähnte Exception. Gibt es in Hibernate eine Möglichkeit evtl. den Default-Wert nochmal separat zu setzen. Ich habe in der API Dokumentation keinen entsprechenden Eintrag gefunden und auch das Buch schweigt sich zu diesem Thema (bisher) aus.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.