GWT + Hibernate many-to-one xml O/R Mapping: SerializationException - java

I'm currently working on a GWT + Hibernate project which should work together on an already defined and filled database. I receive an
com.google.gwt.user.client.rpc.SerializationException
when I query the database.
Here are my objects...
Database:
-- Table: asset
CREATE TABLE IF NOT EXISTS asset
(
isin VARCHAR(12) NOT NULL,
mic_code VARCHAR(4) NOT NULL DEFAULT 'n.a.',
name VARCHAR(255) NOT NULL,
type_id VARCHAR(36) NOT NULL,
PRIMARY KEY (isin, mic_code),
INDEX(isin, mic_code),
FOREIGN KEY (type_id) REFERENCES asset_type(id)
)ENGINE=InnoDB;
-- Table: asset_type
CREATE TABLE IF NOT EXISTS asset_type
(
id VARCHAR(36) NOT NULL,
type VARCHAR(40) NOT NULL,
PRIMARY KEY (id)
)ENGINE=InnoDB;
Asset.java:
public class Asset implements Serializable {
private String isin;
private String mic_code;
private String name;
private AssetType assetType;
public Asset() {
super();
}
...
AssetType.java
public class AssetType implements Serializable {
private String id;
private String type;
public AssetType() {
}
and finally the hibernate xml files:
Asset.hbm.xml
<hibernate-mapping>
<class name="com.mygwtproject.shared.model.Asset" table="ASSET">
<id name="isin" type="java.lang.String" access="field">
<column name="ISIN" />
<generator class="native" />
</id>
<property name="mic_code" type="java.lang.String" access="field">
<column name="MIC_CODE" />
</property>
<property name="name" type="java.lang.String" access="field">
<column name="NAME" />
</property>
<many-to-one name="assetType" class="com.mygwtproject.shared.model.types.AssetType" column="TYPE_ID" cascade="all" not-null="true"/>
</class>
</hibernate-mapping>
AssetType.hbm.xml
<hibernate-mapping>
<class name="com.mygwtproject.shared.model.types.AssetType" table="ASSET_TYPE">
<id name="id" type="java.lang.String" column="ID">
<generator class="native" />
</id>
<property name="type" type="java.lang.String" column ="TYPE" />
</class>
</hibernate-mapping>
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">*****</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/asset_db</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>
<mapping resource="com/mygwtproject/shared/model/Asset.hbm.xml" />
<mapping resource="com/mygwtproject/shared/model/types/AssetType.hbm.xml" />
</session-factory>
</hibernate-configuration>
from log:
Hibernate:
select
assettype0_.ID as ID1_1_0_,
assettype0_.TYPE as TYPE2_1_0_
from
ASSET_TYPE assettype0_
where
assettype0_.ID=?
09:43:09,139 TRACE BasicBinder:81 - binding parameter [1] as [VARCHAR] - [ee5bb49a-dc95-403a-9f77-864a9c342f25]
09:43:09,142 TRACE BasicExtractor:78 - extracted value ([TYPE2_1_0_] : [VARCHAR]) - [Stock]
Starting Jetty on port 8888
[WARN] Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'com.mygwtproject.shared.model.types.AssetType_$$_jvst77c_0' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = com.mygwtproject.shared.model.types.AssetType#7d617ac9
so there is something wrong with my Asset -> AssetType mapping, but i cant find it. Any help is appreciated. thanks
edit:
mysql> select * from asset_type where id = 'ee5bb49a-dc95-403a-9f77-864a9c342f25';
returns
+--------------------------------------+-------+
| id | type |
+--------------------------------------+-------+
| ee5bb49a-dc95-403a-9f77-864a9c342f25 | Stock |
+--------------------------------------+-------+
1 row in set (0.00 sec)

Solution from here:
1. Create counterpart Data Transfer Objects and replace the hibernate objects.
AssetDTO.java
public class AssetDTO implements Serializable {
private String isin;
private String mic_code;
private String name;
private AssetTypeDTO assetType;
public AssetDTO() {
super();
}
public AssetDTO(String isin, String mic_code, String name,
AssetTypeDTO assetType) {
super();
this.isin = isin;
this.mic_code = mic_code;
this.name = name;
this.assetType = assetType;
}
//incl. Getter + Setter
}
AssetTypeDTO.java
public class AssetTypeDTO implements Serializable {
private String id;
private String type;
public AssetTypeDTO() {
super();
}
public AssetTypeDTO(String id, String type) {
super();
this.id = id;
this.type = type;
}
//incl. Getter + Setter
}
2. Add a new constructor to the hibernate objects.
Asset.java
...
public Asset(AssetDTO dto) {
this.isin = dto.getIsin();
this.mic_code = dto.getMic_code();
this.name = dto.getName();
AssetTypeDTO assetTypeDTO = dto.getAssetType();
if (assetTypeDTO != null) {
this.assetType = new AssetType(assetTypeDTO.getId(),
assetTypeDTO.getType());
}
}
...
AssetType.java
public AssetType(AssetTypeDTO dto) {
this.id = dto.getId();
this.type = dto.getType();
}
3. Modify your GWT RPC components.
Replace the Hibernate objects in
IService.java
public List<Asset> getAssets();
with the DTOs.
public List<AssetDTO> getAssets();
IServiceAsync.java
public void getAssets(AsyncCallback<List<Asset>> callback);
with
public void getAssets(AsyncCallback<List<AssetDTO>> callback);
4. Modify your service implementation.
ServiceImpl.java
...
#Override
public List<AssetDTO> getAssets() {
...
Query q = session.createQuery("from Asset");
List<Asset> assets = new ArrayList<Asset>(q.list());
List<AssetDTO> assetsDto = new ArrayList<AssetDTO>();
if (assets != null) {
for (Asset asset : assets) {
assetsDto.add(createAssetDTO(asset));
}
}
session.getTransaction().commit();
return assetsDto;
}
public AssetDTO createAssetDTO(Asset asset) {
AssetTypeDTO assetTypeDto = new AssetTypeDTO(asset.getAssetType()
.getId(), asset.getAssetType().getType());
AssetDTO result = new AssetDTO(asset.getIsin(), asset.getMicCode(),
asset.getName(), assetTypeDto);
return result;
}
...
5. Move the Hibernate objects (Asset, AssetType) to the server package, move the DTOs (AssetDTO, AssetTypeDTO) to the shared package and update the path in your Hibernate xml files.

Related

An attempt was made to modify the identity column ' ID'

I have problem with my project. My apache derby generate id, in table it works. But in app it doesnt work. In derby I set id autoincrement (start with 1, increment by 1), but i get this error:
> Caused by: ERROR 42Z23 : An attempt was made to modify the identity
> column ' ID'
.
My entity:
package com.springapp.mvc.models;
import javax.persistence.*;
#Entity
#Table(name = "USERS", schema = "KK", catalog = "")
public class UsersEntity {
private int id;
private String name;
private String password;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Basic
#Column(name = "PASSWORD")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UsersEntity that = (UsersEntity) o;
if (id != that.id) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
if (password != null ? !password.equals(that.password) : that.password != null) return false;
return true;
}
#Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (password != null ? password.hashCode() : 0);
return result;
}
}
hibernate xml:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:derby://localhost:1527/MyDB</property>
<property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.DerbyDialect</property>
<!-- <property name="hbm2ddl.auto">update</property>
Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<mapping resource="mapping.xml"/>
<mapping class="com.springapp.mvc.models.AccountEntity"/>
<mapping class="com.springapp.mvc.models.BookEntity"/>
<mapping class="com.springapp.mvc.models.UsersEntity"/>
</session-factory>
</hibernate-configuration>
mapping.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.springapp.mvc.models.AccountEntity" table="ACCOUNT" schema="KK">
<id name="id" column="ID"/>
<property name="name" column="NAME"/>
<property name="accountprefix" column="ACCOUNTPREFIX"/>
<property name="accountnumber" column="ACCOUNTNUMBER"/>
<property name="bankcode" column="BANKCODE"/>
<property name="userid" column="USERID"/>
</class>
<class name="com.springapp.mvc.models.BookEntity" table="BOOK" schema="KK">
<id name="id" column="ID"/>
<property name="title" column="TITLE"/>
<property name="description" column="DESCRIPTION"/>
<property name="userid" column="USERID"/>
</class>
<class name="com.springapp.mvc.models.UsersEntity" table="USERS" schema="KK">
<id name="id" column="ID"/>
<property name="name" column="NAME"/>
<property name="password" column="PASSWORD"/>
</class>
</hibernate-mapping>
Thanks
If you set the ID table field to auto-increment then you should not try to insert an id because this is auto generated by derby.
or use Hibernate to generate you id
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
If you define your table this way (either with the GENERATED BY DEFAULT or GENERATED AS ALWAYS keywords)
CREATE TABLE Consultation (id INTEGER PRIMARY KEY NOT NULL GENERATED BY DEFAULT
AS IDENTITY (START WITH 1, INCREMENT BY 1),
Patient_id CHAR(10) NOT NULL REFERENCES PATIENT(CARDNUMBER),
Consultation_date CHAR(20))
you cannot directly insert anything into id. You get this error when you try to do so. You insert data into an Identity field like this:
INSERT INTO CONSULTATION (PATIENT_ID, CONSULTATION_DATE) VALUES ('B2345', '4-8-2016')
This way, the id field is autogenerated for you and incremented when ever you populate a new column.
Note I copied the sql statements above from console in Intellij, to use in a java class, add String concatenation as appropriate:
statement.executeUpdate("INSERT INTO Consultation (PATIENT_ID, CONSULTATION_DATE) VALUES " +
"('2345', '4-8-2016')");

org.hibernate.NonUniqueObjectException when saving a list of child objects

I need to save several child objects when creating the parent object. Ideally, I want to save them in one transaction, however, I keep getting an org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session.
In this example, a SubDiscipline has many SubdisciplinePlayers.
I feel that there's something wrong with the mapping
POJOs:
Subdiscipline.java
public class Subdiscipline {
private int id;
private int disciplineId;
private String name;
private List<SubdisciplinePlayer> subdisciplinePlayers;
public Subdiscipline() {
}
//standard constructors, getter & setters...
}
SubdisciplinePlayers.java
public class SubdisciplinePlayer implements Serializable {
private int idPlayers;
private int disciplineId;
private int subDisciplineId;
private int players;
private int minPlayers;
private int maxPlayers;
private Subdiscipline subdiscipline;
public SubdisciplinePlayer() {
}
//standard constructors, getter & setters...
}
Main.java:
public class Main {
#SuppressWarnings("unchecked")
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Subdiscipline sd = new Subdiscipline("soccer_" + (new Date()).getTime(), new Date(), new Date(), new Status(1) );
sd.setDisciplineId(4);
session.save(sd);
SubdisciplinePlayer sdp = new SubdisciplinePlayer();
sdp.setDisciplineId(sd.getDisciplineId());
sdp.setSubDisciplineId(sd.getId());
sdp.setSubdiscipline(sd);
sdp.setIdPlayers(555);
SubdisciplinePlayer sdp2 = new SubdisciplinePlayer();
sdp2.setDisciplineId(sd.getDisciplineId());
sdp2.setSubDisciplineId(sd.getId());
sdp2.setSubdiscipline(sd);
sdp2.setIdPlayers(457);
sd.setSubdisciplinePlayers(new ArrayList<SubdisciplinePlayer>());
sd.getSubdisciplinePlayers().add(sdp);
sd.getSubdisciplinePlayers().add(sdp2);
session.save(sd);
session.getTransaction().commit();
session.close();
}
}
Mappings
Subdiscipline Mapping
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="net.viralpatel.hibernate.Subdiscipline" table="sub_discipline">
<id name="id" column="sub_dis_id" unsaved-value="0">
<generator class="increment"/>
</id>
<property name="disciplineId" column="dis_id" type="int"/>
<property name="name" column="sub_discipline" type="string"/>
<bag name="subdisciplinePlayers" table="sdis_players" inverse="true" cascade="all">
<key column="sub_dis_id" />
<one-to-many class="net.viralpatel.hibernate.SubdisciplinePlayer" />
</bag>
</class>
</hibernate-mapping>
SubdisciplinePlayer Mapping
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="net.viralpatel.hibernate.SubdisciplinePlayer" table="sdis_players">
<composite-id>
<key-property name="disciplineId" column="dis_id" type="int"/>
<key-property name="subDisciplineId" column="sub_dis_id" type="int" />
</composite-id>
<property name="idPlayers" column="id_players" type="int"/>
<property name="players" column="players" type="int"/>
<property name="minPlayers" column="min_players" type="int"/>
<property name="maxPlayers" column="max_players" type="int"/>
<many-to-one name="subdiscipline" class="net.viralpatel.hibernate.Subdiscipline" cascade="none" insert="false" update="false">
<column name="sub_dis_id"/>
</many-to-one>
</class>
</hibernate-mapping>
Exception thrown
Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [net.viralpatel.hibernate.SubdisciplinePlayer#net.viralpatel.hibernate.SubdisciplinePlayer#1cd7e9c3]
You have declared composite key with fields disciplineId & subDisciplineId for your entity SubdisciplinePlayer.
Now in your program you are creating 2 instances of SubdisciplinePlayer with same composite id.
SubdisciplinePlayer sdp = new SubdisciplinePlayer();
sdp.setDisciplineId(sd.getDisciplineId());
sdp.setSubDisciplineId(sd.getId());
SubdisciplinePlayer sdp2 = new SubdisciplinePlayer();
sdp2.setDisciplineId(sd.getDisciplineId());
sdp2.setSubDisciplineId(sd.getId());
So when you call Session.save(sd), hibernate observed that you are trying to save 2 instances of SubdisciplinePlayer and throwing the exception as :
org.hibernate.NonUniqueObjectException: a different objectwith the same identifier
value was already associated with the session:
[net.viralpatel.hibernate.SubdisciplinePlayer#
net.viralpatel.hibernate.SubdisciplinePlayer#1cd7e9c3]
To fix the issue just make sure that the composite id of SubdisciplinePlayer should have different values as primary key should be unique.
Please use merge instead of save when you are trying with second time save.
sd.setSubdisciplinePlayers(new ArrayList<SubdisciplinePlayer>());
sd.getSubdisciplinePlayers().add(sdp);
sd.getSubdisciplinePlayers().add(sdp2);
session.merge(sd);
I listed out more ref for you.
Ref 1
Ref 2

create template for hibernate mapping files

How can I create (if I can) a template file for my hbm.xml files to use while they are being created from JAVA class?
I am using Jboss Hibernate Tools 3.5.1 and Eclipse Indigo
You can find a detailed description below.
Thanks for your help.
My JAVA classes are coded carefully to represent the sql table. they all have the same syntax.
for instance lets say I have the following table in my db:
Tests (id int primary key, TestData varchar(255), Type int)
a class referring to this table is:
public class TestData {
int id;
String testData;
int type;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTestData() {
return testData;
}
public void setTestData(String testData) {
this.testData = testData;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
When I create an automated hbm.xml file for this class it comes out as:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 12.Ara.2013 12:33:42 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.entegrator.framework.persistent.TestData" table="TESTDATA">
<id name="id" type="int">
<column name="ÝD" />
<generator class="assigned" />
</id>
<property name="testData" type="java.lang.String">
<column name="TESTDATA" />
</property>
<property name="type" type="int">
<column name="TYPE" />
</property>
</class>
</hibernate-mapping>
as you can see, my first problem is encoding.
what else I want to do is
property column names and class table name should be converted appropriately
id generator class should be "identity"
You have to change them manually if you are creating hbm file using eclipse.
Other options are you can use annotations or create files our own to remove this extra headache.!!!
you can get more about the same at Hibernate

Hibernate criteria returns empty result

I want to retrieve data from the database (Oracle) using Hibernate.
I want to select all columns from a view. The view has no primary key, so I used composite key in the Hibernate-mapping.
Firstly my class:
public class MyBean implements Serializable {
private MyBeanId compId;
private String col1;
private String col2;
// getters and setters
}
Where the MyBeanId class:
public class MyBeanId implements Serializable {
private int id1;
private int id2;
// getters and setters, hashCode and equals
}
The Hibernate mapping:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.mypackage">
<class name="MyBean" table="MY_TABLE">
<composite-id name="compId" class="MyBeanId ">
<key-property column="COL_ID1" name="id1" type="int"/>
<key-property column="COL_ID2" name="id2" type="int"/>
</composite-id>
<property name="col1" type="string">
<column name="COL1" />
</property>
<property name="col2" type="string">
<column name="COL2" />
</property>
</class>
</hibernate-mapping>
My DAO (MyBeanManagerImpl):
public List<MyBean> getMyBeans(Session session) {
try {
Criteria criteria = session.createCriteria(MyBean.class);
List<MyBean> list = criteria.list();
System.out.println(list.toString());
return list;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
And my table MY_TABLE:
ID1,ID2,COL1,COL2
1,2,"a","b"
3,2,"c","d"
The result is an empty list. I've verified there's data in my table. When I use other managers in my service, there's no problem getting the result so there's no problem with the session.
There's no Exception thrown at all, so it is strange it doesn't get any result.
Add mapping-resource entry for the new mapping in yours hibernate-configuration -> session factory configuration like you have for other already mapped classes.
See the link https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Hibernate_Core_Reference_Guide/tutorial.html#tutorial-firstapp-configuration Chapter 'Hibernate configuration' there you have example of hibernate.cfg.xml. You need to add <mapping-resouce ... entry

Hibernate: Using collection of complex objects throws exceptions

I am looking into Hibernate and storing collections of complex types. But I run into exception.
I have the following persistent class:
public class Item {
private Long id;
private Set images = new HashSet();
private Collection<Data> data = new ArrayList<Data>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set getImages() {
return images;
}
public void setImages(Set images) {
this.images = images;
}
public Collection<Data> getData() {
return data;
}
public void setData(Collection<Data> data) {
this.data = data;
}
}
The Data class is as follows:
public class Data {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public boolean equals(Object obj) {
if(!(obj instanceof Data) )
return false;
Data d = (Data) obj;
if(d.firstName.equals(firstName) && d.lastName.equals(lastName))
return true;
return false;
}
#Override
public int hashCode() {
int result;
result = 17;
result = 31 * result + firstName.hashCode();
result = 31 * result + lastName.hashCode();
return result;
}
The mapping files are as follows:
For Item class:
<hibernate-mapping>
<class name="com.entities.Item" table="ITEM">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="identity" />
</id>
<set name="images" table="ITEM_IMAGE" inverse="false" lazy="true">
<key>
<column name="ID" />
</key>
<element type="string">
<column name="IMAGES" />
</element>
</set>
<bag name="data" table="DATA" inverse="false" lazy="true">
<key>
<column name="ID" />
</key>
<one-to-many class="com.entities.Data" />
</bag>
</class>
</hibernate-mapping>
For Data class:
<hibernate-mapping>
<class name="com.entities.Data" table="DATA">
<id name="firstName" type="java.lang.String">
<column name="FIRSTNAME" />
<generator class="assigned" />
</id>
<property name="lastName" type="java.lang.String">
<column name="LASTNAME" />
</property>
</class>
</hibernate-mapping>
In my code to save data to MySQL:
Transaction tx = session.beginTransaction();
Item item = new Item();
Set images = new HashSet();
images.add("C:\\");
images.add("D:\\");
item.setImages(images);
List<Data> data = new ArrayList<Data>();
Data a = new Data();
a.setFirstName("John");
a.setLastName("Smith");
data.add(a);
item.setData(data);
session.save(item);
tx.commit();//-->Exception here
session.close();
I get the following exception on tx.commit();
Hibernate: insert into ITEM values ( ) Hibernate: insert into
ITEM_IMAGE (ID, IMAGES) values (?, ?) Hibernate: insert into
ITEM_IMAGE (ID, IMAGES) values (?, ?) Hibernate: update DATA set ID=?
where FIRSTNAME=? Hibernate: update DATA set ID=? where FIRSTNAME=?
1454 [main] ERROR org.hibernate.jdbc.AbstractBatcher - Exception
executing batch: org.hibernate.StaleStateException: Batch update
returned unexpected row count from update [0]; actual row count: 0;
expected: 1 at
org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
at
org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
at
org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90)
at
org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at
org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
at
org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at
org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188)
at
org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at
org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216) at
org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383) at
org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at com.entities.Main.main(Main.java:44)
Why do I get this exception?
If I remove the Collection<Data> data to store only the Set the code works and the data are saved in MySQL.
Note: The mapping files have been created by Eclipse Hibernate plugin.
Made the following changes to your code :
Transaction tx = session.beginTransaction();
Item item = new Item();
//added save here to attach the object to persistance context.
// (This might be optional)
session.save(item);
Set images = new HashSet();
images.add("C:\\");
images.add("D:\\");
item.setImages(images);
List<Data> data = new ArrayList<Data>();
Data a = new Data();
a.setFirstName("John");
a.setLastName("Smith");
//added save here to attach the object to persistance context.
//this is required without cascading settings
session.save(a)
data.add(a);
item.setData(data);
session.save(item);
tx.commit();//-->Exception here
session.close();
You could otherwise set appropriate the cascading options on the bag!
AFAIK you are getting the error since you are trying to persist an association without the other entity (Data) being in persistant state and the cascading options are set to none by default. Again I haven't tried out to run my piece of snippet but this will point you in the right direction.
UPDATE from the OP:
The problem is solved by using inverse="true", doing cascade and also I have to reference from Data to Item otherwise the FK column is not updated
Is it possibly due to the fact that you're adding a to the list data twice?

Categories