Hibernate Version 3.3.1 GA-dist
MySql 5.1
Java 6
I posted this before under a different and had lots of suggestions but non of them panned out.
My understanding is that if I create a UserVo and add an EmailAddress to UserVo.email list and then save the UserVo, hibernate should save the email as well and save the user_id so that I can retrieve that email later for that UserVo.
The table structure created by hibernate is correct, but the problem I have is that the value in the email.user_id column is null if I take out the not-null attribute.
How do I make hibernate save the user and the email, with all of the data in the table?
This is what I get when I have the not-null out of hbms
mysql> select * from email;
+----------+---------+---------------+
| email_id | user_id | email_address |
+----------+---------+---------------+
| 1 | NULL |
me@here.com |
+----------+---------+---------------+
1 row in set (0.00 sec)
This is what I get when I have the not-null in there.
Console output:
Hibernate: insert into users (first_name) values (?)
Exception in thread "main" org.hibernate.PropertyValueException: not-null property references a null or transient value: com.example.apps.reports.vo.EmailAddress.user
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:95)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:534)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:526)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:241)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:291)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:239)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:192)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:319)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:265)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:192)
at org.hibernate.engine.Cascade.cascade(Cascade.java:153)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:479)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:357)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:534)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:526)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:522)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:342)
at $Proxy0.saveOrUpdate(Unknown Source)
at com.example.apps.reports.service.DataService.saveItem(DataService.java:15)
at com.example.apps.reports.service.DataService.main(DataService.java:28)
Java Classes:
package com.example.apps.reports.service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Session;
import com.example.apps.reports.dao.HibernateUtil;
import com.example.apps.reports.vo.EmailAddress;
import com.example.apps.reports.vo.UserVo;
import com.example.apps.reports.vo.ValueObject;
public class DataService {
public static void saveItem(ValueObject vo){
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.saveOrUpdate(vo);
session.getTransaction().commit();
}
public static void main(String[] args) {
UserVo u = null;
EmailAddress e = null;
u = new UserVo();
u.setFirstName("Me");
e = new EmailAddress();
e.setEmailAddress("me@here.com");
ArrayList emails = new ArrayList();
emails.add(e);
u.setEmail(emails);
DataService.saveItem(u);
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
u = (UserVo) session.createQuery("from UserVo where userId = ?").setInteger(0, 1).uniqueResult();
session.getTransaction().commit();
System.out.println(u.getFirstName());
List ems = u.getEmail();
for (Iterator iterator = ems.iterator(); iterator.hasNext();) {
EmailAddress x = (EmailAddress) iterator.next();
System.out.println(x.getEmailAddress());
}
}
}
package com.example.apps.reports.vo;
public class ValueObject {
}
package com.example.apps.reports.vo;
import java.util.List;
public class UserVo extends ValueObject{
private int userId;
private String firstName;
private List email;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public List getEmail() {
return email;
}
public void setEmail(List email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
package com.example.apps.reports.vo;
public class EmailAddress extends ValueObject{
private int emailId;
private UserVo user;
private String emailAddress;
public int getEmailId() {
return emailId;
}
public void setEmailId(int emailId) {
this.emailId = emailId;
}
public UserVo getUser() {
return user;
}
public void setUser(UserVo user) {
this.user = user;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
hibernate.cfg.xml:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/hibernatetest</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<mapping resource="com/example/apps/reports/vo/mappings/UserVo.hbm.xml"/>
<mapping resource="com/example/apps/reports/vo/mappings/EmailAddress.hbm.xml"/>
</session-factory>
</hibernate-configuration>
HBMs:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.example.apps.reports.vo.EmailAddress" table="email">
<id name="emailId" column="email_id">
<generator class="native"/>
</id>
<many-to-one name="user" column="user_id" not-null="true" foreign-key="user_id" class="com.example.apps.reports.vo.UserVo" />
<property name="emailAddress" column="email_address" type="java.lang.String"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.example.apps.reports.vo.UserVo" table="users">
<id column="user_id" name="userId">
<generator class="native"/>
</id>
<property name="firstName" column="first_name"/>
<bag name="email"
cascade="all"
inverse="true"
lazy="false"
table="email">
<key column="user_id"
not-null="true"
/>
<one-to-many class="com.example.apps.reports.vo.EmailAddress"/>
</bag>
</class>
</hibernate-mapping>
SQL that hibernate generated for table creation:
CREATE TABLE `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`user_id`)
ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
CREATE TABLE `email` (
`email_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`email_address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`email_id`),
KEY `user_id` (`user_id`),
CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`)
ENGINE=InnoDB DEFAULT CHARSET=latin1