Primary key not updating when inserting data to database using hibernate - java

I'm new to hibernate and postgres. I need help regarding primary key in hibernate. This is the problem: When I inserted data using persist() for the first time, it was a success. Now, when I inserted the next data, my IDE gave me this error:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique
constraint "test1_tbl2_pkey"
Detail: Key (id)=(0) already exists.
It seems like the value in the sequence is not used. Because the initial value of a sequence in postgres is 1. Also, when I looked at the tables, their primary key values are 0. How to tell hibernate to use the sequence in my postgres database? I'm new to both technologies thus, I'm having a hard time solving this problem.
tbl1_mappings.hbm.xml
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="pojo.Test1Tbl1" table="test1_tbl1" schema="public">
<id name="id" type="integer" column="id">
<generator class="increment"/>
</id>
<property name = "name" column = "tbl1_name" type = "string"/>
<one-to-one name="tbl2"></one-to-one>
</class>
</hibernate-mapping>
tbl2_mappings.hbm.xml
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="pojo.Test1Tbl2" table="test1_tbl2" schema="public">
<id name = "id" type = "integer" column = "id">
<generator class="foreign"/>
</id>
<property name = "name" column = "tbl2_name" type = "string"/>
</class>
</hibernate-mapping>
Event code of my button
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
Test1Tbl2 tbl2 = new Test1Tbl2(field2.getText());
Test1Tbl1 tbl1 = new Test1Tbl1(field1.getText(), tbl2);
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
session.persist(tbl2);
session.persist(tbl1);
tx.commit();
}
catch(HibernateException ex) {
ex.printStackTrace();
}
catch(Exception ex) {
ex.printStackTrace();
}
}

After I've done my intensive research, I found a solution. Although, this solution doesn't use the persist() method. However, this solution does update the primary key via postgres sequence. Btw, I'm using Hibernate 6.1.2.Final version.
This is the code that I came up with:
Transaction tx = null;
try (Session session = factory.openSession()){
tx = session.beginTransaction();
String query = "INSERT INTO test1_tbl1(tbl1_name)" +
"VALUES ('"+field1.getText()+"');";
MutationQuery mq = session.createNativeMutationQuery(query);
int result = mq.executeUpdate();
System.out.println("Rows affected: " + result);
tx.commit();
}
catch(Exception ex) {
if (tx!=null) tx.rollback();
ex.printStackTrace();
}
Take note that I severed the relationship between test1_tbl1 and test1_tbl2 tables and I only used test1_tbl1 to make my answer more clear. This article helps me to create the solution above:
MutationQuery and SelectionQuery
Other articles propose to use the 'sequence' generator class in the mapping file to fix the problem. Ex:
<id name="id" type="integer" column="id">
<generator class="sequence">
<param name="sequence_name">my_sequence</param>
</generator>
</id>
Although, this solution doesn't work for me. I also tried using different types of generator classes like native, identity and auto; still they didn't work.
These are some articles that I've stumbled upon that are related to the problem mentioned in this thread:
Hibernate doesn't use PostgreSQL sequence to generate primary key
JPA and PostgreSQL with GenerationType.IDENTITY
How To Use Sequence In Hibernate As A Property In XML Mapping
HIbernate 5: generator class="sequence" not working
Migrating Hibernate 3 to 5: relation hibernate_sequence does not exist
JPA GenerationType.AUTO not considering column with auto increment
Edit:
I decided to play around and I found the solution that I'm looking for. In your cfg.xml, remove hibernate.transform_hbm_xml.enabled property. This property is messing up the generator classes. However, removing the property will make this warning appear in your logs:
WARN: HHH90000028: Support for `<hibernate-mappings/>` is deprecated [RESOURCE : resources/mappings/tbl1_mappings.hbm.xml]; migrate to orm.xml or mapping.xml, or enable `hibernate.transform_hbm_xml.enabled` for on the fly transformation
Switching to JPA annotation style with persistence.xml fixes this warning for me.
Btw, this is my cfg.xml:
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name = "hibernate.dialect">
org.hibernate.dialect.PostgreSQLDialect
</property>
<property name = "hibernate.connection.driver_class">
org.postgresql.Driver
</property>
<property name = "hibernate.connection.url">
jdbc:postgresql://localhost:3308/hibernate_test
</property>
<property name="hibernate.default_schema">
public
</property>
<property name = "hibernate.connection.username">
postgres
</property>
<property name = "hibernate.connection.password">
password
</property>
<property name = "hibernate.id.new_generator_mappings">
true
</property>
<!-- List of XML mapping files -->
<mapping resource="resources/mappings/tbl1_mappings.hbm.xml"/>
</session-factory>
</hibernate-configuration>
The hibernate.id.new_generator_mappings property is a flag that sets the generator mapping style to old style if it's set to false. Otherwise, sets the mapping style to new style.
I think this article has simple explanation about the property:
HIbernate 5: generator class="sequence" not working

Related

Java_Hibernate 3_CLOB_ORA-01461

I added a new CLOB Column in a table and modified my hbm.xml - file to use this new column (the old column was varchar2 and therefore too small):
(I used random-names for demonstration purposes)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="test.com.TestDO" table="TESTTABLE">
<id name="id" type="java.lang.Integer">
<column name="ID"/>
<generator class="sequence">
<param name="sequence">SEQ_SEQUENCENAME</param>
</generator>
</id>
</property>
<property name="columnName1" type="java.util.Date">
<column name="COLUMN_NAME1"/>
</property>
<property name="columnName2" type="java.lang.String">
<column name="COLUMN_NAME2"/>
</property>
<property name="columnName3" type="java.lang.String">
<column name="COLUMN_CLOB"/>
</property>
</class>
</hibernate-mapping>
As you can see, my clob-column (COLUMN_CLOB) is defined as last, because first I got this exception:
ORA-24816: Expanded non LONG bind data supplied after actual LONG or LOB column
I searched for this error and the solution was to place the clob binding at the last in the insert-statement, so I defined the clob-column in the hbm.xml file to be last, as you can see above.
Now I am not getting the ORA-24816 exception, but I am getting this exception:
ORA-01461: can bind a LONG value only for insert into a LONG column
The generated Insert-Statement looks like this:
insert into TESTTABLE(COLUMN_NAME1, COLUMN_NAME2, COLUMN_CLOB, ID) values (?, ?, ?, ?)];
As you may have noticed, the COLUMN_CLOB - column does not appear last in the generated Insert-Statement. I don't know if the order in the hbm-xml -file affects the order of the columns in the generated insert-statement?
But anyway, I am not getting the ORA-24816 anymore just ORA-01461. I don't know how to solve this issue.
I am using Hibernate 3 and Oracle Version: Enterprise Edition Release 11.2.0.4.0 - 64bit Production
EDIT:
I have the exact same issue as described here:
http://newtechnobuzzz.blogspot.ch/2014/07/ora-24816-expanded-non-long-bind-data.html#.Wcy-QdFpHRY
I have tried the following solutions:
Chaning the order of getter and setter methods does not work
Changing the order of the declared property in the hbm.xml -file does
not work
The problem described on the link and on other sites, state that this excpetion
occurs if you try to insert data in both the varchar2 and the clob columns (2 strings with a length of 4000). However I am only inserting data into the clob-column which is bigger then 4000. I am not using the old varchar2 - column anymore.
Now, I am trying to solve this by using this solution:
It can solved by writing two update queries. Firstly, save/update the entity by an Update query and then write another query to update LOB columns in that entity.
However, I dont quite understand, how I should modify my code. My method looks like this:
#Override
#Transactional(readOnly=false, propagation=Propagation.MANDATORY)
public TestDO saveTest(TestDO test) {
getHibernateTemplate().saveOrUpdate(test);
return test;
}
From what I can see, the property type has not been declared correctly for the CLOB column, try that:
<property name="columnName3" length="100000" type="StringClob">
<column name="COLUMN_CLOB"/>
</property>

org.hibernate.MappingException: Repeated column in mapping for entity

I am using Hibernate 3.2.5. I am getting the above exception while using many-to-one mapping. The training table is having a many to one relation with Department table, i.e. One Depatement is capable of taking more than one training.
The exception is asking me to add insert="false" update="false" in my hbm file. If I add this bit in hbm file, then the code works fine.
Here is the hbm file:
<?xml version="1.0" encoding="UTF-8"?>
<!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.infy.model.Training" table="training">
<id name="Id" type="integer" column="ID">
<generator class="assigned"></generator>
</id>
<property name="trainerName">
<column name="TRAINER_NAME"></column>
</property>
<property name="deptId">
<column name="DEPT_ID"></column>
</property>
<property name="trainingSubject">
<column name="TRAINING_SUBJECT"></column>
</property>
<many-to-one name="departmentDetails" column="DEPT_ID"></many-to-one>
</class>
</hibernate-mapping>
If I change this line to:
<many-to-one name="departmentDetails" column="DEPT_ID" insert="false" update="false"></many-to-one>
Then the code works. I want to know what is the exact reason for adding this.
Regards,
You have mapped the DEPT_ID column twice, here:
<property name="deptId">
<column name="DEPT_ID"></column>
</property>
And here:
<many-to-one name="departmentDetails" column="DEPT_ID"></many-to-one>
When executing a select statement, Hibernate will be fine populating two properties of your object from the same column, however when doing an insert or an update it cannot decide which property to persist in the database.
Why do you need two properties mapped to the same column in the first place? If you need access to the deptId, you can probably remove the deptId property and instead do
training.getDepartmentDetails().getId()
The error message for this scenario is quite clear (you haven't put it here, but I've seen it a few times). The problem is that you've mapped the column DEPT_ID to two different fields in your class.
First, you've mapped it to the property deptId and then to departmentDetails. As you found out, hibernate allows to do this only if one of the mappings is configured to be insert="false" update="false".
The reason is quite simple. If you would change deptId to another id, hibernate would need to change the class that is mapped in departmentDetails, which is quite complicated.
if you need to get the deptId, you can add a getDeptId method on Training that returns departmentDetails.getId(). And don't provide a setDeptId.
If you are using the same column name twice in your mapping file. might be you get mapping Exception
Initial SessionFactory creation failed.org.hibernate.MappingException:
Also if u mark insert=flase and update=false .
if u try to update or insert in records in table or another legacy system try to update these column value. it wouldn't update or insert that filed.
Please check the below link .it will help to find your solutions.
http://www.techienjoy.com/hibernate-insert-update-control.php
Thanks
Sandeep G.

org.hibernate.ObjectNotFoundException: No row with the given identifier exists, but it DOES

I've got a hibernate problem that I can't fix.
The setup: Java EE, web app, Hibernate 3.2, Tomcat 6, Struts 2.
Basically, I persist an object with my server logic (a struts action), then try and pull that data out for the next page and display it.
I check the database after I save the object, and sure enough, I can see the row there with all the data.
But when I try and retrieve it I get this:
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [msc.model.Picture#73]
To make things even muddier, when I restart Tomcat and try and access the same object, I don't get the error - Hibernate finds the row just fine.
Hibernate will also be able to see the row if I do some other operations - maybe add a row here and there to the database, not even on the same table.
From all this I suspect a Hibernate bug, but I'm a Hibernate newbie so I am probably wrong. Please help! I've googled and googled to no avail.
Here is my Hibernate config:
<?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="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/msc</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">-------</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">80</property>
<property name="current_session_context_class">thread</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<mapping resource="msc/model/Picture.hbm.xml"/>
<mapping resource="msc/model/Comment.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Here are my two mapping files:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="msc.model.Picture" table="PICTURE">
<id column="PICTURE_ID" name="id">
<generator class="native"/>
</id>
<property name="story"/>
<property name="email"/>
<property name="category"/>
<property name="state"/>
<property name="ratings"/>
<property name="views"/>
<property name="timestamp"/>
<property name="title"/>
<property lazy="true" name="image" type="blob">
<column name="IMAGE"/>
</property>
<property lazy="true" name="refinedImage" type="blob">
<column name="REFINEDIMAGE"/>
</property>
<property lazy="true" name="thumbnail" type="blob">
<column name="THUMBNAIL"/>
</property>
<bag cascade="save-update" lazy="true" name="comments" table="COMMENT">
<key column="PICTURE"/>
<one-to-many class="msc.model.Comment"/>
</bag>
</class>
</hibernate-mapping>
and
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="msc.model.User" table="USER">
<id column="USER_ID" name="id">
<generator class="native"/>
</id>
<property name="username"/>
<property name="email"/>
<bag cascade="save-update" lazy="true" name="pictures" table="PICTURE">
<key column="USER"/>
<one-to-many class="msc.model.Picture"/>
</bag>
<bag cascade="save-update" lazy="true" name="comments" table="COMMENT">
<key column="USER"/>
<one-to-many class="msc.model.Comment"/>
</bag>
</class>
</hibernate-mapping>
Please let me know if you need more info, I'm happy to oblige.
(note: this is not a duplicate of this question, the scenario is not the same "No row with the given identifier exists" although it DOES exist)
EDIT: as requested, posting Java code:
Code to save object
Session hib_ses = HibernateUtil.getSessionFactory().getCurrentSession();
hib_ses.beginTransaction();
hib_ses.save(user);
hib_ses.getTransaction().commit();
Code to display data (an image in this case)
public class ImageAction extends ActionSupport implements ServletResponseAware, SessionAware {
private HttpServletResponse response;
Map session;
private Long id;
private int thumbnail;
private InputStream inputStream;
#Override
public String execute() throws Exception {
response.setContentType("image/jpeg");
Session hib_session = HibernateUtil.getSessionFactory().getCurrentSession();
hib_session.beginTransaction();
//what is the ID now?
Picture pic = (Picture) hib_session.load(Picture.class, getId());
if (thumbnail == 1) {
inputStream = (ByteArrayInputStream) pic.getThumbnail().getBinaryStream();
} else {
inputStream = (ByteArrayInputStream) pic.getRefinedImage().getBinaryStream();
}
hib_session.close();
return SUCCESS;
}
This happens because you have inserted something which is meant to be a foreign key but do not reference anything.
Check out you database whether that key exist or not(even though it is in database in other tables).
Check all your mappings and database settings. It may be possible you are setting some not-null="true" in foreign key relations when your database says nullable="true". The first causes an INNER JOIN and the second causes LEFT JOIN.
Set log level to TRACE to see all steps and look for generated SQL when retrieving the objects.
In many to one relationship you need to tell Hibernate what needs to be done if the mapped row is not found. You can configure it in the following ways:
Annotation:
#NotFound(action = NotFoundAction.IGNORE)
Mapping XML:
<many-to-one name="user" column="user_id" class="com.xyz.User" cascade="save-update, evict" not-found="ignore"/>
Just check your database whether id 73 is available or not in your particular table
Okay, I am going to throw out a theory here. Could it be that you are trying to load the picture the first time before the transaction has been committed?
Since the transaction is not yet committed, the row is not visible to the transaction you are using for reading the picture (depends on what transaction isolation level you have).
Then, since hib_session.close() is not inside a finally block, it will not be executed, and the thread-bound session will still have an open transaction. The subsequent request gets the same Hibernate session, with the same open transaction, and you get the same result from the select it issues (again, dependent on transaction isolation level - see documentation here, in particular for REPEATABLE_READ).
This could also explain why flush() makes it slightly better, because if the flush() occurs earlier than the commit(), there's a smaller chance for the race condition to occur.
I suggest you try closing the session in a finally block and see if the behavior changes for subsequent requests.
I Faced this issue and here is What happened and How i resolved it. You most probably have the same thing going on too.
I had POST and USER objects. They are in a OneToMany relationship(A user can have many posts). Making it bidirectional they are in a ManyToOne relationship too (one post belongs to only one user).
Post class looks
#Entity
#Table(name="Post")
public class Post {
#Id
#GeneratedValue(strategy=GenerationType.TABLE)
private long postId;
private String title;
private String body;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "postUserId")
private AutoUser autoUser;
// getter and setters
User class is
#Entity
#Table(name = "AUTO_USER")
public class AutoUser implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long autoUserId;
#Column(name = "USERNAME")
private String username;
#OneToMany
private List<Post> postList = new ArrayList<>();
// getter and setters
The first table names were Post and AUTO_USER I had 3 users persisted to a AUTO_USER table(with id 1, 2, 3).. And 3 entry to the Post table 1 for each user.
(the join columns or foreign key were 1, 2, 3)
Then I changed only the table name for the user object only and named it #Table(name = "AUTO_USER2").
and I had only one user in this table with id 1.
In my code I iterate over each post and identify which post belongs to which user and display them those belonging to the current logged in user.
After changing the post table name I got this exception
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.tadtab.core.authentication.AutoUser#2
Which is telling me that the user object with id 2 is not available in the new user Table.
then I registered one more user with id 2 and later I got this
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.tadtab.core.authentication.AutoUser#3
This time it could not find user with id 3
Finally registered a third user and had not exception.
As you can see, the foreign key exists in the post table but since I changed the user table, there could not be a match for them and that is the reason I was facing this issue.
To avoid that situation I created new table names for both objects and started fresh
Hope this will help
I don't see any real problems pertaining to the exception in the code, you might wanna try:
Checking that the transaction is flushed or calling flush() manually after committing;
Checking whether the ID is passed to load() and whether the right ID is passed to it via debugger
Enabling Hibernate to print the generated SQL and/or enabling logging
I have a similar problem with hibernate 3.6.10, while I'm just searching and selecting (if exist).
Annotation:
#Entity
public class Familiares {
#OneToMany(mappedBy = "familiares")
private List<FamiliaresBaja> bajas;
#Entity
#Table(name = "familiares_baja")
public class FamiliaresBaja implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#JoinColumn(name = "familiares_id")
#ManyToOne(optional = false)
private Familiares familiares;
then i retrieve a List and with these looking in FamiliaresBaja if there is at least one.
createQuery("from FamiliaresBaja where familiares.id="+ id).uniqueResult() // should return a single result or null not throw a Exception
This must be a Hibernate bug
Please check the value of lower_case_table_names of your mysql server. If its value is 0, check the SQL generated by hibernate, make sure the table name's case is consistent with the actual table name in mysql.
Check triggers, if you have a before insert trigger, and having NEXTVAL in the sequence, cause that error.
You may have a one-to-one relationship in the entity you are looking for with a different ID, try to load the entity with the ID in the mapped table rather then the identity column.
The correct way to solve this problem is to use session.get() method. Get method will return null if entity is not found.
Caused by: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.emmanuel.Entity.Classe#17]
at org.hibernate.boot.internal.StandardEntityNotFoundDelegate.handleEntityNotFound(StandardEntityNotFoundDelegate.java:28)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:216)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:327)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118)
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1215)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1080)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:697)
at org.hibernate.type.EntityType.resolve(EntityType.java:464)
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240)
at org.hibernate.engine.internal.TwoPhaseLoad$EntityResolver.lambda$static$0(TwoPhaseLoad.java:576)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntityEntryLoadedState(TwoPhaseLoad.java:221)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:155)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:126)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1201)
at org.hibernate.loader.Loader.processResultSet(Loader.java:1009)
at org.hibernate.loader.Loader.doQuery(Loader.java:967)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:357)
at org.hibernate.loader.Loader.doList(Loader.java:2868)
at org.hibernate.loader.Loader.doList(Loader.java:2850)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2682)
at org.hibernate.loader.Loader.list(Loader.java:2677)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:109)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1906)
at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:370)
I had this same problem, I had previously deleted an object which was referenced in another table and when I loaded the objects I had a foreign key in the table which did not refer to anything hence this exception.
[com.emmanuel.Entity.Classe#17] specifies that the object which is referenced with id 17 in the table whose objects I want to load does not exist.
My issue was that the child in the relation had a FK which didn't map to the PK of the parent so I had to change the JoinColumn to include referencedColumnName
#Entity
#Table(name = "child")
class Child {
#ManyToOne
#JoinColumn(name = "child_id", referencedColumnName = "non_pk_parent_id")
var iabCategory: IabCategory
}
Note that this caused another issue because of a bug in Hibernate. Here's a stackoverflow post on it:
Jpa Repository got error cannot not serializable when get data from database
and the link to the Hibernate bug: https://hibernate.atlassian.net/browse/HHH-7668
This bug forced me to mark the parent Serializable
#Entity
#Table(name = "parent")
class Parent : Serializable {
}
The bug would cause a ClassCastException to be thrown if the parent didn't implement Serializable

Hibernate not loading associated object

i am trying to load a hibernate object ForumMessage but in it contain another object Users and the Users object is not being loaded.
My ForumMessage Mapping File:
<?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 Jan 4, 2011 10:10:29 AM by Hibernate Tools 3.4.0.Beta1 -->
<hibernate-mapping>
<class name="com.BiddingSystem.Models.ForumMessage" table="FORUMMESSAGE">
<id name="ForumMessageId" type="long">
<column name="FORUMMESSAGEID" />
<generator class="native" />
</id>
<property name="ForumMessage" type="java.lang.String">
<column name="FORUMMESSAGE" />
</property>
<many-to-one name="User" class="com.BiddingSystem.Models.Users" fetch="join">
<column name="UserId" />
</many-to-one>
<property name="DatePosted" type="java.util.Date">
<column name="DATEPOSTED" />
</property>
<many-to-one name="Topic" class="com.BiddingSystem.Models.ForumTopic" fetch="join">
<column name="TopicId" />
</many-to-one>
</class>
</hibernate-mapping>
and I am using the follwing code:
Session session = gileadHibernateUtil.getSessionFactory().openSession();
SQL="from ForumMessage";
System.out.println(SQL);
Query query=session.createQuery(SQL);
System.out.println(query.list().size());
return new LinkedList <ForumMessage>(query.list());
<many-to-one name="User" class="com.BiddingSystem.Models.Users" fetch="join" lazy="false">
You need to add lazy="false" as well.
You can add lazy="false" to the many-to-one mapping which will load the users when the ForumMessage is loaded. Alternatively you could initialize the users list using Hibernate.initialize(). Just make sure you do this before you close the session.
Session session = gileadHibernateUtil.getSessionFactory().openSession();
string sql = "from ForumMessage";
Query query = session.createQuery(sql);
List results = query.list()
for(ForumMessage message : results)
{
Hibernate.initialize(message.User);
}
return new LinkedList <ForumMessage>(results);
You should only do one of these though if you have a need to. Hibernate by default lazy loads objects to avoid unnecessary calls to the database. For example:
public LinkedList getMessages()
{
//It's assumed the session is opened and closed elsewhere.
string sql = "from ForumMessage";
Query query = session.createQuery(sql);
List results = query.list();
//The overhead of extra calls to the database occur here.
//This would have a similar impact if lazy load is set to false.
for(ForumMessage message : results)
{
Hibernate.initialize(message.User);
}
return new LinkedList <ForumMessage>(results);
}
public void printMessages()
{
LinkedList messages = getMessages();
for(ForumMessage message : messages)
{
System.out.println(message.ForumMessage);
}
}
In the above code sample the overhead is incurred for loading all the Users objects but those objects are never used. If Hibernate's lazy-loading were used then this extra overhead would not be incurred. In the following example the list of users isn't loaded until the list is used. This way calls are not made to the database until the data is actually needed.
public LinkedList getMessages()
{
//It's assumed the session is opened and closed elsewhere.
string sql = "from ForumMessage";
Query query = session.createQuery(sql);
List results = query.list();
return new LinkedList <ForumMessage>(results);
}
public void printMessages()
{
LinkedList messages = getMessages();
for(ForumMessage message : messages)
{
//Hibernate will load the users objects here when they are accessed.
for(Users user : message.User)
{
System.out.println(user);
}
}
}
One point to be careful of when lazy loading is all loading must be done in an active session. If you don't have an active session and you try and access something that has not yet been loaded Hibernate will throw a LazyInitializationException.
In addition, using Hibernate's lazy load functionality complies more with the idea of persistence ignorance where as using Hibernate.initialize() does not.

Issue in Adding data into database using hibernate

I am getting the following exception while adding data into database:
org.hibernate.HibernateException: The database returned no natively generated identity value
I am using the following code:
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
session.save(user);
logger.info("Successfully data insert in database");
tx.commit();
isSaved = true;
Please let me know what is wrong. Thankx
It seems as if the database doesn't support the identity id generator. Based on your mapping you are probably using the userName as the ID column, which would mean that you probably want to set the generator class to assigned since the username (= id) will be picked manually (and not auto generated by the database):
<hibernate-mapping>
<class name="com.test.User" table="user">
<id name="userName" column="user_name">
<generator class="assigned" />
</id>
<property name="userCode">
<column name="user_code" />
</property>
</class>
</hibernate-mapping>

Categories

Resources