Hibernate version: 3.1
Friends,
We found that inactivating entities was a common routine across our application. So we decided to have a generic dao implementation that simply updates the active field of our entity table to false. We are using HQL for this as we only want to update the one "active" field rather than have all fields of the entity updated.
The DAO method :
Code:
public void deactivate(Object entity) {
Session session = getSession();
Method getIdMethod = entity.getClass().getMethod("getId", null);
Method setActiveMethod = entity.getClass().getMethod("setActive", Boolean.class);
// Get the id of the entity being updated
Object id = getIdMethod.invoke(entity, null);
// Prepare the HQL query
String hqlUpdate = "UPDATE " + entity.getClass().getName() + " c SET c.active = :active WHERE c.id = :id";
Query query = session.createQuery(hqlUpdate)
.setBoolean("active", false);
.setString("id", id.toString());
int entitiesUpdated = query.executeUpdate();
setActiveMethod.invoke(entity, new Boolean(false));
}
This works well with normal single-column primary key fields, but fails with composite-key type ids.
If I attempt to set the id as :
Code:
Object id = getIdMethod.invoke(entity, null);
...
Query query = session.createQuery(hqlUpdate)
.setBoolean("active", false);
query.setParameter("id", id);
I get the below logs :
Code:
Hibernate: update stock_item set name=?, item_code=?, active=? where first_id=? and second_id=?
Hibernate: update stock_item set active=? where (first_id, second_id)=?
Apr 17, 2006 2:34:59 PM org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 1241, SQLState: 21000
Apr 17, 2006 2:34:59 PM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: null, message from server: "Operand should contain 2 column(s)"
org.hibernate.exception.DataException: could not execute update query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:75)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.hql.ast.exec.BasicExecutor.execute(BasicExecutor.java:80)
at org.hibernate.hql.ast.QueryTranslatorImpl.executeUpdate(QueryTranslatorImpl.java:324)
at org.hibernate.impl.SessionImpl.executeUpdate(SessionImpl.java:1047)
at org.hibernate.impl.QueryImpl.executeUpdate(QueryImpl.java:89)
at test.Tester.main(Tester.java:133)
Caused by: java.sql.SQLException: null, message from server: "Operand should contain 2 column(s)"
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1905)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1109)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1203)
at com.mysql.jdbc.Connection.execSQL(Connection.java:2090)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1680)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1527)
at org.hibernate.hql.ast.exec.BasicExecutor.execute(BasicExecutor.java:71)
... 4 more
There are a couple of things that are perplexing here.
1. Why is Hibernate firing two update statements ?
2. Why is the composite id comparison clause different in the two statements ?
Mapping documents:Code:
<hibernate-mapping package="test" >
<class name="StockItem" table="stock_item" >
<composite-id name="id" class="ItemId" >
<key-property name="firstId" type="integer" column="first_id" />
<key-property name="secondId" type="integer" column="second_id" />
</composite-id>
<property column="name" name="name" type="string" not-null="true" type="string" />
<property column="active" name="active" type="boolean" not-null="true"/>
</class>
Is it possible to achieve the generic-ness by using this approach ? Any alternate ways if not ? Any inputs would be welcome.
TIA.