org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update - java

In my module that I'm working on, I got this error, which is said caused by org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
and java.sql.BatchUpdateException (the full stack trace is in here : click here).
From what I've read from other posts, this is surely caused by violation of primary key. However I couldn't even replicate the problem so that I can at least trace the real bug and solve the problem. Every time I inserted an identical entry with the one which already in the database, it will simply merge with each other and no error. However, I was getting many of this error in the deployment, so I'm not quite sure what's going on in the deployment server (I'm just a student developer, so I'm still kinda 'noob' in this).
I would appreciate it even if anyone can point me to the direction. Thanks. (Inform me if there's something need to be added)
Here is the snippet of hibernate mapping for the module (hope this would help) :
<hibernate-mapping package="edu.umd.cattlab.schema.cattXML.extensions.VaTraffic"
default-lazy="false" default-cascade="all, delete-orphan" schema="vatraffic">
<typedef class="edu.umd.cattlab.schema.hibernate.util.XMLGregorianCalendarType" name="XMLCal"/>
<class name="VaTrafficAssociatedEvent" table="associated_event">
<id name="associatedEventId" column="associated_event_id">
<generator class="sequence">
<param name="sequence">ritis.associated_event_id_seq</param>
</generator>
</id>
<property name="secondaryEventId" column="secondary_event_id" not-null="true" />
<property name="unassociatedTimestamp" type="XMLCal" column="unassociated" />
<property name="autoRelated" column="auto_related" not-null="true" />
<many-to-one name="relationshipType" column="relationship_type" not-null="true" cascade="none" />
</class>
This is the part of java code that utilizes the above mapping: click here

You can have more constraints than just a primary key constraint. Could it be you have a foreign key constraint that you are violating? Or maybe a multiple column unique constraint. Could you please include the DDL for the table you are updating?

In reviewing the logs, it is a violation of the pk constraint. Specifically ERROR: duplicate key violates unique constraint "associated_event_pk"
Trying to determine why this is happening may be a deep dive, but for starters how are you generating values for this field? In your ddl it shows as a "nextval" field but your log appears to indicate there is an explicit value. Where is this value coming from? Why are you not letting postgre set the value itself?

Related

Using "SELECT FOR UPDATE OF" with Hibernate 4 & Postgres

I'm using Postgres 9.3.5 and recently updated the hibernate from 3.2 to 4.3.11.
As a result I can't run "SELECT... FOR UPDATE OF" queries,
and simply 'select.. for update' is not enough in my case since it returns
could not extract ResultSet. Reason: ERROR: FOR UPDATE cannot be applied to the nullable side of an outer join
The criteria I'm trying to use looks like this:
Criteria criteria = session.createCriteria(objectType).add(Restrictions.eq("name", objectName).ignoreCase());
I'm using the following locking:
in 3.2: criteria.setLockMode(LockMode.UPGRADE);
in 4.3.11: criteria.setLockMode(LockMode.PESSIMISTIC_WRITE);
I have an hierarchy of hibernate (& DB) objects which cause the hibernate perform several joins while constructing the above query.
the 'objectType' is a joined-subclass of the main class
<class name="BaseObject" table="BASE_OBJECTS">
While using hibernate 3.2 the final query (taken from Postgres logs) ended with: "for update of this_2_"
(when this_2_ is the alias given by hibernate to the main table (BaseObject) mapped in hbm.xml file)
After upgrading to 4.3.1.1 the same query returns the above mentioned exception.
which means the final query performed as for update (without the name of the table on which to perform the lock)
After an extensive look of the web I could find only that the "for update of" in hibernate with Postgres is not supported any more?
[https://hibernate.atlassian.net/browse/HHH-5654][2]
It seems very unlikely since it's quite an important sql feature and a big degradation in usage.
Am I missing something here?
02.09.15:
I'll try to clarify myself:
using an example given in the hibernate documentation
at
https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/inheritance.html
class name="Payment" table="PAYMENT">
<id name="id" type="long" column="PAYMENT_ID">
<generator class="native"/>
</id>
<property name="amount" column="AMOUNT"/>
...
<joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">
<key column="PAYMENT_ID"/>
<property name="creditCardType" column="CCTYPE"/>
...
</joined-subclass>
<joined-subclass name="CashPayment" table="CASH_PAYMENT">
<key column="PAYMENT_ID"/>
...
</joined-subclass>
<joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT">
<key column="PAYMENT_ID"/>
...
</joined-subclass>
If I want to perform something like:
select p from Payment p where id=1
Hibernate will perform an outer join (on the key) on all tables .
Adding a lock (.setLockMode(LockMode.PESSIMISTIC_WRITE)) will lock the lines on the four tables (as 'For update'),
instead of only on table "Payments" ('for update of p') - which did happen in hibernate 3.2
So what We have, is that Something which was supplied earlier by hibernate, is not working any more, using their own mapping examples?
Thanks in advance
Marina
The issue was fixed in Hibernate 5.
Tested in 5.2.8.Final.

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.

LONG as primary key in Hibernate mapping to MySQL

I am trying to implement persistence of some Java objects via Hibernate mapping to a MySQL table. When I commit I get a message saying 'Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1'.
My hypothesis is that the problem is caused from having a long-field in my Java POJO that I want to use as my primary key in the MySQL table. Since I was not able to use datatype LONG as my primary key in MySQL table (ERROR 1170: BLOB/TEXT column 'id' used in key specification without a key length) I concluded from some googling and this post that BIGINT would be the suitable mapping for long. However it is not updating.
My test POJO Personis very simple. It has 3 fields: id (long), firstname (String), lastname (String) with setters and getters, etc.
I do the hibernate mapping in xml (person.hbm.xml) that essentially looks like (minus headings):
<hibernate-mapping>
<class name="hibernatetest.Person" table="hibernatetest">
<id name="id" type="long" column="id" >
<generator class="native"/>
</id>
<property name="firstname">
<column name="firstname" />
</property>
<property name="lastname">
<column name="lastname"/>
</property>
</class>
</hibernate-mapping>
My actual java code snippet that is supposed to save or update the record is simple:
Transaction tr = session.beginTransaction();
Person person = new Person(1,"John","Doe");
session.saveOrUpdate(person);
tr.commit();
And here's that thing, this all works just fine if I change the type of id to an int (Integer) in the Person object and in the MySQL table. However, I do not have that option for the actual objects that I want to persist so the question is; what am I doing wrong or what should I do to get it to work? Thanks.
ADDING Stacktrace:
Hibernate: update hibernatetest set firstname=?, lastname=? where id=?
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:81)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:57)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3006)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2908)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3237)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:113)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:187)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1082)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:317)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at com.hibernate.test.TestMain.main(TestMain.java:38)
nested transactions not supported
UPDATE:
OK, I have finally worked it out. I changed the hibernate generator class from 'native' to 'assigned' and now it works as expected. So now the hibernate mapping looks like:
<hibernate-mapping>
<class name="hibernatetest.Person" table="hibernatetest">
<id name="id" type="long" column="id" >
<generator class="assigned"/>
</id>
<property name="firstname">
<column name="firstname" />
</property>
<property name="lastname">
<column name="lastname"/>
</property>
</class>
</hibernate-mapping>
Must admit I did not know the meaning of that parameter (copied from somewhere) and had no idea it could cause this much headache. Found this explanation which was quite useful.
Apparently I do not have enough credentials to answer my own questions so I guess that it will remain open or if someone provides an empty answer, I will accept it. Thanks.
When you use the saveOrUpdate() method hibernate fires the insert query if the id of the object is null and update if it is any other value. I can see the code,
Person person = new Person(1,"John","Doe"); setting the id to 1 and calling the saveOrUpdate() method. I am assuming there are no entries for the id 1 and hence the error is thrown.
To make it work, you need to make the below changes.
Change the Type of id in person to Long from long(The wrapper class so that it can support null).
Write the constructor new Person("John","Doe"); and save that object.
It is not a good Idea to keep the <generator class="assigned"/> for the transactional data. Instead you should be sticking to the native as you were trying first.
I feel this is a cleaner way to solve your initial problem, even though you have found an alternate solution.

Hibernate Initial SessionFactory creation failed

I'm trying to use hibernate to fill my jsf selectonemenu in ApplicationBean (in Liferay). The problem is that I got Initial SessionFactory creation failed problem. Before putting my functions in the applicationbean I was setting them in sessionbean and I got no error.
For now the full error
Initial SessionFactory creation failed.
java.lang.ClassCastException: org.hibernate.type.StringType cannot be cast to org.hibernate.type.VersionType
You have very likely a VARCHAR column called VERSION somewhere and Hibernate's reverse engineering tool generates it as:
<version name="version" type="string">
<column name="VERSION" length="20" />
</version>
instead of:
<property name="version" type="string">
<column name="VERSION" length="20" />
</property>
The former is wrong. First, I think that this is not what you want. Second, a string is not allowed for a version field as mentioned in the chapter 5.1.9. Version (optional):
Version numbers can be of Hibernate type long, integer, short, timestamp or calendar.
This problem has been somehow reported in HHH-3002 (actually, it should be assigned to Hibernate Tools, not Hibernate Core) and I see two ways to solve it. Either
fix the mapping manually
rename the column to something else.
The property on one of your domain classes that you've mapped as the class's version is of type string. This is not a valid type for a version. What to change it to will depend on how you are implementing versioning in your underlying database.

Hibernate Reference column in table to indicate how to unmarshall an attribute in a different column in the same table

I have an entity that I want to persist through Hibernate (3.2)
The EntityBean has a column that indicates how another value of the entity bean should be unmarshalled:
<class name="ServiceAttributeValue" table="service_attribute_value">
<cache usage="nonstrict-read-write"/>
<id name="id" column="id" type="int-long">
<generator class="native"/>
</id>
<property name="serviceAttribute" type="service-attribute" column="service_attribute" not-null="true" />
<!-- order is important here -->
<property name="value" type="attribute-value" not-null="true">
<column name="service_attribute" />
<column name="id_value"/>
<column name="enum_value"/>
<column name="string_value"/>
<column name="int_value"/>
<column name="boolean_value"/>
<column name="double_value"/>
</property>
</class>
The "service_attribute" column indicates which of the columns for the "value" property to look at when it unmarshalls the value and, more importantly, exactly what Type the value should be, for example the class of the Enum if the enum_value is to be read, or the type of Bean if the the id_value is to be read.
The value property uses a custom CompositeUserType to do the unmarshalling and within this I wish to reference the service_attribute column (although not write to it), however when I try to do this I get the following error:
org.hibernate.MappingException: Repeated column in mapping for entity: com.precurse.apps.rank.model.service.ServiceAttributeValue column: service_attribute (should be mapped with insert="false" update="false")
However within the definition of the composite property these xml attributes are not defined (only within a normal property).
Does anyone know of a way of overcoming this, or if there is a better solution to this propblem.
If you need any more information please let me know,
Cheers
Simon
I had a similar problem and changing the case of one column solved the problem. Could give a try!
e.g., one column could be service_attribute other Service_Attribute.
You can try this. Instead of mapping both values as property on the same table, map one of the property using join to itself and keep the other property as the way it is. This case you will be able to access the same property in both places. Just remember to name the property as different name.
<join table="service_attribute_value">
<key column = "id" />
<property name="serviceAttribute" type="service-attribute" column="service_attribute" not-null="true" />
</join>
<!-- order is important here -->
<property name="value" type="attribute-value" not-null="true">
<column name="service_attribute" />
<column name="id_value"/>
<column name="enum_value"/>
<column name="string_value"/>
<column name="int_value"/>
<column name="boolean_value"/>
<column name="double_value"/>
</property>
based on your description, it seems like what you want to do is creating different subclasses based on the service_attribute. Instead of trying to achieve repeated column mapping which is not allow in hibernate, you can take a look hibernate inheritance mapping.
I Think I found a solution albeit not a very elegant one.
in the
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
method of the CompositeUserType the "owner" argument passed to the method contains the id of the object who's service_attribute I want to access.
Annoyingly the actual serviceAttribute of the owner is not accessable or has not been set at this stage (I played around with the ordering of the elements in the hbm.xml config, in case this was an ordering thing, but unfortunatly still no joy), so I can't simply access it.
Anyway the id of the owner object is set, so I then used the session argument to run a HQL query based on the id to access the serviceAttribute which I then used to correctly unmarshall the value property.
The drawback of this solution is that it requires a HQL query as an overhead to the unmarshalling process, although its within the same session, its still not optimal.
If anyone has any ideas for a better solution I'd be very grateful.
Cheers

Categories

Resources