| If you've been working with Hibernate 3 and using Hibernate Annotations, you've probably noticed that the Hibernate guys did not create an annotation for the unsaved-value attribute for identifiers. They don't feel that Hibernate Annotations needs this functionality and that Hibernate has enough smarts in place to do the right thing in almost all situations. Well, I have a situation where entities are being remoted from an Adobe Flex client through BlazeDS remoting to a Java service hosted in an Apache Tomcat server. The Flex client cannot assign nulls to Number ActionScript types, which the Java Long id value maps to. Therefore, for new entities, I set the id value on the Flex side to -1 and transfer it across the wire to the Java side for persistence. Initially this caused Hibernate to try to update a non-existent row in the database. After some searching, I came upon the idea that I should use a Hibernate Interceptor and give Hibernate a bit of a hint as to what to do with entities coming across the wire from Flex. Here's the interceptor: package goodeats.hibernate; import goodeats.domain.AbstractDomainObject; import org.hibernate.EmptyInterceptor; import org.hibernate.Interceptor; public class NewEntityInterceptor extends EmptyInterceptor implements Interceptor { private static final long serialVersionUID = 2914362528125673753L; @Override public Boolean isTransient(Object n) { Boolean result = Boolean.FALSE; AbstractDomainObject entity = (AbstractDomainObject) n; if (entity.getId() == -1L) { entity.setId(null); result = Boolean.TRUE; } return result; } } I'm using Spring with Hibernate, so the configuration of the NewEntityInterceptor occurs in the Spring application context configuration file. <!-- ======================================================================================= --> <!-- Hibernate interceptor --> <!-- ======================================================================================= --> <bean id="hibernateInterceptor" class="goodeats.hibernate.NewEntityInterceptor" /> <!-- ======================================================================================= --> <!-- Hibernate transaction manager --> <!-- ======================================================================================= --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> <property name="entityInterceptor" ref="hibernateInterceptor" /> </bean> Now I can send my object over from Flex with an id value of -1 and Hibernate will properly determine that an insert SQL statement needs to be executed to persist this domain object's state to the database. |