Hi,
I am newie to Hibernate, in my development, I update one table that has a unique key constraint. says "workPhaseId + parentId + ord + level"
Now I want to switch the ord of 2 records.
Example,
before switch : A with "10000 + 100 + 2 + 1"
B with "10000 + 100 + 3 + 1"
After switch : A with "10000 + 100 + 3 + 1"
B with "10000 + 100 + 2 + 1"
So that I
1. update A.ord to 0
2. update B.ord to 2
3. update A.ord to 3
Sounds easy, right?
But after tx.commit();
I found that A.ord = 0, B.ord = 2.
I am so frustrated and come for help finally.
Below is the attached code.
Would you please kindly tell me why this happen?
I even try the connection inside session.
Debug in the transaction I can see A.ord = 3.
but after commit it turns out to be 0.
Thank you very much in advance.
Hibernate version:
hibernate-2.1.4
Mapping documents:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<!--
Created by the Middlegen Hibernate plugin
http://boss.bekk.no/boss/middlegen/
http://hibernate.sourceforge.net/
-->
<class
name="com.gearteks.imanage.model.Phase"
table="phase"
>
<meta attribute="class-description" inherit="false">
@hibernate.class
table="phase"
</meta>
<id
name="phaseId"
type="java.lang.Integer"
column="PhaseId"
>
<meta attribute="field-description">
@hibernate.id
generator-class="assigned"
type="java.lang.Integer"
column="PhaseId"
</meta>
<generator class="assigned" />
</id>
<property
name="description"
type="java.lang.String"
column="Description"
length="255"
>
<meta attribute="field-description">
@hibernate.property
column="Description"
length="255"
</meta>
</property>
<property
name="level"
type="int"
column="Level"
not-null="true"
unique="true"
length="3"
>
<meta attribute="field-description">
@hibernate.property
column="Level"
length="3"
not-null="true"
</meta>
</property>
<property
name="ord"
type="int"
column="Ord"
not-null="true"
unique="true"
length="3"
>
<meta attribute="field-description">
@hibernate.property
column="Ord"
length="3"
not-null="true"
</meta>
</property>
<property
name="parentId"
type="int"
column="ParentId"
not-null="true"
unique="true"
length="8"
>
<meta attribute="field-description">
@hibernate.property
column="ParentId"
length="8"
not-null="true"
</meta>
</property>
<property
name="phaseName"
type="java.lang.String"
column="PhaseName"
not-null="true"
length="64"
>
<meta attribute="field-description">
@hibernate.property
column="PhaseName"
length="64"
not-null="true"
</meta>
</property>
<!-- associations -->
<!-- bi-directional one-to-many association to Job -->
<set
name="jobs"
lazy="true"
inverse="true"
>
<meta attribute="field-description">
@hibernate.set
lazy="true"
inverse="true"
@hibernate.collection-key
column="PhaseId"
@hibernate.collection-one-to-many
class="com.gearteks.imanage.model.Job"
</meta>
<key>
<column name="PhaseId" />
</key>
<one-to-many
class="com.gearteks.imanage.model.Job"
/>
</set>
<!-- bi-directional many-to-one association to WorkPhase -->
<many-to-one
name="workPhase"
class="com.gearteks.imanage.model.WorkPhase"
not-null="true"
>
<meta attribute="field-description">
@hibernate.many-to-one
not-null="true"
@hibernate.column name="WorkPhaseId"
</meta>
<column name="WorkPhaseId" />
</many-to-one>
</class>
<query name="Phase_getByWorkPhaseId">
<![CDATA[ Select p from Phase as p where p.workPhase = ? order by level, parentId, ord]]>
</query>
<query name="Phase_getMaxOrderByParentId">
<![CDATA[ Select max(ps.ord) from Phase as ps where ps.parentId = ? ]]>
</query>
<query name="Phase_getByUniqueKey">
<![CDATA[ Select p from Phase as p where p.level = ? and p.parentId = ? and
ord = ? and p.workPhase = ? ]]>
</query>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
public final ActionForward execute(ActionMapping mapping,
ActionForm form,
javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws java.lang.Exception {
LOG.trace("Opening Hibernate session");
Transaction tx = null;
ActionForward aForward = null;
try {
beforeTrans(mapping, form, request, response);
_session = HibernateUtil.currentSession();
_session.setFlushMode(getFlushMode());
tx = _session.beginTransaction();
LOG.trace("Invoking Action command");
aForward = super.execute(mapping, form, request, response);
LOG.trace("Committing Hibernate Transaction");
tx.commit();
afterTrans(mapping, form, request, response);
} catch (Exception e) {
LOG.error("Exception invoking Action command" +
" or committing Hibernate Transaction",
e);
if (tx != null) {
tx.rollback();
}
throw e;
} finally {
HibernateUtil.closeSession();
}
return aForward;
}
public void movePhaseToNext(Phase phase, boolean isMoveUp)
throws GTSystemException {
if (phase == null) {
throw new IllegalArgumentException("Cannot perform move phase to" +
" next function for null.");
}
Phase siblingPhase = getNextSiblingPhase(phase, isMoveUp);
if (siblingPhase == null) {
return;
}
int order = phase.getOrd();
phase.setOrd(siblingPhase.getOrd());
siblingPhase.setOrd(0);
Session session = null;
java.sql.Connection conn = null;
java.sql.PreparedStatement ps = null;
java.sql.ResultSet rs = null;
//update(siblingPhase);
//update(phase);
try {
session = HibernateUtil.currentSession();
//session.update(siblingPhase);
conn = session.connection();
ps = conn.prepareStatement(
"Update Phase set ord = ? Where PhaseId = ?");
ps.setInt(1, siblingPhase.getOrd());
ps.setInt(2, siblingPhase.getId());
ps.executeUpdate();
ps.setInt(1, phase.getOrd());
ps.setInt(2, phase.getId());
ps.executeUpdate();
ps.setInt(1, order);
ps.setInt(2, siblingPhase.getId());
ps.executeUpdate();
//session.update(phase);
} catch (Exception e) {
throw new GTSystemException(e);
} finally {
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
} catch (Exception e) {
throw new GTSystemException(e);
}
}
//siblingPhase.setOrd(order);
//update(siblingPhase);
}
Full stack trace of any exception that occurs:
N/A
Name and version of the database you are using:
MySql 5.x
Debug level Hibernate log excerpt:
N/A