-->
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.  [ 6 posts ] 
Author Message
 Post subject: [Newbie] - Problem with primairy key
PostPosted: Thu Apr 10, 2008 7:12 am 
Newbie

Joined: Wed Apr 02, 2008 3:59 am
Posts: 6
Location: Netherlands, Amsterdam
Hi all,

I recently started with hibernate. I have created a business object called textMessage and I want to store it. For the database I have SQL Server 2005, in the database I created a new table called TEXT_MESSAGE and I created a couple of columns. MESSAGE_ID (Primairy key), MESSAGE, SEND_DATE, SENDER_ID and API_MESSAGE_ID.

My business object looks as follows:

Code:
import java.util.Date;

import javax.persistence.*;

@Entity
@Table(name="TEXT_MESSAGE")
public class TextMessage {
   private Long id;
   private String message;
   private String senderId;
   private Date sendDate;
   private String apiMessageId;
   
   public TextMessage() {}

   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="MESSAGE_ID")
   public Long getId() {
      return id;
   }

   public void setId(Long id) {
      this.id = id;
   }

   
   @Column(name="MESSAGE")
   public String getMessage() {
      return message;
   }
   
   public void setMessage(String message) {
      this.message = message;
   }


   @Column(name="SENDER_ID")
   public String getSenderId() {
      return senderId;
   }

   public void setSenderId(String senderId) {
      this.senderId = senderId;
   }
   
   @Column(name="SEND_DATE")
   public Date getSendDate() {
      return sendDate;
   }

   public void setSendDate(Date sendDate) {
      this.sendDate = sendDate;
   }
   
   @Column(name="API_MESSAGE_ID")
   public String getApiMessageId() {
      return apiMessageId;
   }

   public void setApiMessageId(String apiMessageId) {
      this.apiMessageId = apiMessageId;
   }
   
}


Now I have a DAO class with a method to store the textMessage:
Code:
public class TextMessageDAO {
   
   public void storeTextMessage(TextMessage textMessage) {
      //Start EntityManagerFactory
      EntityManagerFactory emf = Persistence.createEntityManagerFactory("ricohUnit");
      
      //First unit of work
      EntityManager em = emf.createEntityManager();
      EntityTransaction tx = em.getTransaction();
      
      tx.begin();

      em.persist(textMessage);

      tx.commit();
      em.close();      
      emf.close();   
   }
}


Now when I execute this method I get an error telling me that the value NULL cannot be inserted into column MESSAGE_ID.
Ofcourse that is correct, it is set as the primairy key.
Code:
Hibernate:
    insert
    into
        TEXT_MESSAGE
        (API_MESSAGE_ID, MESSAGE, SEND_DATE, SENDER_ID)
    values
        (?, ?, ?, ?)
13:00:21,269  WARN JDBCExceptionReporter:77 - SQL Error: 515, SQLState: 23000
13:00:21,269 ERROR JDBCExceptionReporter:78 - Cannot insert the value NULL into column 'MESSAGE_ID', table 'Ricoh-PoC.dbo.TEXT_MESSAGE'; column does not allow nulls. INSERT fails.


Why is Hibernate not inserting MESSAGE_ID with a generated value?

Cheers,
Rick


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 10, 2008 9:37 am 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
I think hibernate is expecting you to have an auto-incremental field configured at the table-level.
Is this schema being generated with hibernate? make sure you have it updated. using
Code:
hibernate.hbm2ddl.auto=validate

or
Code:
hibernate.hbm2ddl.auto=update

may help.

regards,
Sanne


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 10, 2008 10:30 am 
Newbie

Joined: Wed Apr 02, 2008 3:59 am
Posts: 6
Location: Netherlands, Amsterdam
Thanks

The =validate helped me work out some issues with the database (it expected some different column types.)

But it did not mention anything about the MESSAGE_ID column. So I tried the auto increment on table-level. That worked!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 10, 2008 10:51 am 
Newbie

Joined: Wed Apr 02, 2008 3:59 am
Posts: 6
Location: Netherlands, Amsterdam
Now I tried an extra step:

I have a second business object named Receiver ..... it is a many to many relation with TextMessage

The new TextMessage class:
Code:
import java.util.Date;
import java.util.List;
import java.util.Vector;

import javax.persistence.*;

import org.hibernate.annotations.CollectionId;

@Entity
@Table(name="TEXT_MESSAGE")
public class TextMessage {
   private Long id;
   private String message;
   private String senderId;
   private Date sendDate;
   private String apiMessageId;
   private List<Receiver> receivers = new Vector<Receiver>();
   
   public TextMessage() {}
   
   @Column(name="MESSAGE")
   public String getMessage() {
      return message;
   }
   
   public void setMessage(String message) {
      this.message = message;
   }

   @ManyToMany
   @CollectionId(
         columns = @Column(name="TEXTMESSAGE_RECEIVER_ID"),
         type=@org.hibernate.annotations.Type(type="long"),
         generator="sequence"
   )
   @JoinTable(
         name="TEXTMESSAGE_RECEIVER",
         joinColumns={@JoinColumn(name="MESSAGE_ID")},
         inverseJoinColumns={@JoinColumn(name="RECEIVER_ID")}
   )
   public List<Receiver> getReceivers() {
      return receivers;
   }

   public void setReceivers(List<Receiver> receivers) {
      this.receivers = receivers;
   }
   
   public void addReceiver(Receiver receiver) {
      receivers.add(receiver);
   }
   
   public void removeReceiver(Receiver receiver) {
      receivers.remove(receiver);
   }

   @Column(name="SENDER_ID")
   public String getSenderId() {
      return senderId;
   }

   public void setSenderId(String senderId) {
      this.senderId = senderId;
   }
   
   @Column(name="SEND_DATE")
   public Date getSendDate() {
      return sendDate;
   }

   public void setSendDate(Date sendDate) {
      this.sendDate = sendDate;
   }
   
   @Column(name="API_MESSAGE_ID")
   public String getApiMessageId() {
      return apiMessageId;
   }

   public void setApiMessageId(String apiMessageId) {
      this.apiMessageId = apiMessageId;
   }
   
   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name = "MESSAGE_ID")
   public Long getId() {
      return id;
   }

   public void setId(Long id) {
      this.id = id;
   }
}

The Receiver class
Code:
import java.util.List;

import javax.persistence.*;

@Entity
@Table(name="RECEIVER")
public class Receiver {
   private Long id;
   private String name;
   private String surName;
   private String mobileNumber;
   
   @ManyToMany(mappedBy="receivers")
   private List<TextMessage> textMessages;
   
   public Receiver() {}
   
   @Column(name = "NAME")
   public String getName() {
      return name;
   }
   
   public void setName(String name) {
      this.name = name;
   }
   
   @Column(name = "SURNAME")
   public String getSurName() {
      return surName;
   }
   public void setSurName(String surName) {
      this.surName = surName;
   }
   
   @Column(name = "MOBILE_NUMBER")
   public String getMobileNumber() {
      return mobileNumber;
   }
   
   public void setMobileNumber(String mobileNumber) {
      this.mobileNumber = mobileNumber;
   }
   
   public List<TextMessage> getTextMessages() {
      return textMessages;
   }
   public void setTextMessages(List<TextMessage> textMessages) {
      this.textMessages = textMessages;
   }
   public void addTextMessage(TextMessage textMessage) {
      textMessages.add(textMessage);
   }
   public void removeTextMessage(TextMessage textMessage) {
      textMessages.remove(textMessage);
   }
   
   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name= "RECEIVER_ID")
   public Long getId() {
      return id;
   }

   public void setId(Long id) {
      this.id = id;
   }
}


I found the examples in the JP with Hibernate book and online.
When I try to run the Unit test now to store the TextMessage I get the following error:

Code:
javax.persistence.PersistenceException: org.hibernate.MappingException: Could not determine type for: java.util.List, for columns: [org.hibernate.mapping.Column(textMessages)]
   at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:737)
   at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:121)
   at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:51)
   at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:33)
   at ditp.ricoh.persistence.TextMessageDAO.storeTextMessage(TextMessageDAO.java:20)
   at ditp.ricoh.service.TextMessageSO.storeTextMessage(TextMessageSO.java:71)
   at UNIT_storage.storeTextMessage(UNIT_storage.java:62)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
   at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
   at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
   at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
   at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
   at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
   at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
   at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
   at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
   at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
   at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.List, for columns: [org.hibernate.mapping.Column(textMessages)]
   at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:266)
   at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:253)
   at org.hibernate.mapping.Property.isValid(Property.java:185)
   at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:440)
   at org.hibernate.mapping.RootClass.validate(RootClass.java:192)
   at org.hibernate.cfg.Configuration.validate(Configuration.java:1102)
   at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1287)
   at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:915)
   at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:730)
   ... 26 more


If I'm reading it correctly it says it can not determine the type for java.util.List with HibernateMapping. It does so for the column textMessages .... so that should be a problem in the Receiver object then.

What type should I use for these collections of entity classes so Hibernate understand what it is?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 10, 2008 1:03 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
Hi,
I will help you translate this, so next time you may understand what hibernate is telling you:
Quote:
MappingException: Could not determine type for: java.util.List, for columns: [org.hibernate.mapping.Column(textMessages)

wat the stacktrace is saying is that he doesn't know how to map
the type of the the method:
Code:
public List<TextMessage> getTextMessages()


You didn't annotate this method with some @ManyToMany or @OneToMany
so you didn't tell him you want to map a relation to a list/collection/set of other entities. If this would have been a normal object (not a collection nor an interface) it would serialize the object to a BLOB column.
As it is an interface (and List is not serializable) he doesn't know how to map it.

You probably wanted it to be marked by @ManyToMany, and as it looks like you are defining a bi-directional relationship you are going to set at least the mappedBy parameter.
Please read the reference documentation for more details about bidirectional relationships.

regards,

Sanne


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 11, 2008 3:47 am 
Newbie

Joined: Wed Apr 02, 2008 3:59 am
Posts: 6
Location: Netherlands, Amsterdam
Thanks that helped I moved the @ManyToMany(mappedBy="receivers") from above the
Code:
private List<TextMessage> textMessages;

to the method:
Code:
public List<TextMessage> getTextMessages() {
      return textMessages;
   
}


I'll look some more in the documentation and the book JP with Hibernate about many-to-many relationships


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.