Hibernate UserType nullSafeSet - 如何知道是否调用insert / update或select

时间:2009-09-25 03:38:20

标签: java hibernate

我有一个自定义UserType,它在TIMESTAMP字段中存储日期/时间值,并在插入或更新记录时更新为当前时间'UTC'。 (此字段不用于版本控制或id用途​​。)

问题是这非常好用但是如果你需要运行一个查询,其中这个字段是构建预准备语句时的标准之一,则会调用自定义用户类型nullSafeSet,它将值设置为当前时间,以便查询始终将该条件设置为当前时间,但不会产生所需的结果。

是否可以使nullSafeSet知道调用它的上下文,以便它可以调整插入/更新或选择的行为。或许还有另一种方法可以做到这一点?

我尝试过使用< timestamp ... />但它不会以UTC格式写入值。 (后备数据库是Derby,它本身并不能很好地处理时区。)我也尝试过更新replace(...)方法中的值,但这仅在实体与会话分离时才有效然后带回来。从一些代码中,实体在单个会话上下文中被检索和更新,因此该字段不会更新。

是否仍然可以使用自定义用户类型以UTC格式写入值,但是只使用某种生成器来获取插入和更新时的当前日期/时间?

package example;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Properties;
import java.util.TimeZone;

import org.hibernate.HibernateException;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;

/**
 * The class DateTimestampUserType implements a Hibernate 
 * UserType to allow the persistence of Date 
 * instances as a TIMESTAMP in the database.
 * 
 * All Date instances persisted are in UTC/GMT time.  
 * 
 * This UserType implementation also allows for a boolean parameter
 * 'updateToNow' specified as part of Hibernate configuration. This parameter
 * controls whether when a Date needs to be persisted it is updated 
 * to the current time.  This is useful for fields like TimeModified as it 
 * requires no intervention by the calling code.
 */
public class DateTimestampUserType implements UserType, ParameterizedType {

   /* Constants */
   private static final String UTC_TZ = "GMT";

   /* Member Variables */
   private boolean m_updateToNow = false;

   /* Methods */
   /* (non-Javadoc)
    * @see org.hibernate.usertype.ParameterizedType#setParameterValues(java.util.Properties)
    */
   public void setParameterValues(Properties parameters) {
      if (parameters != null && parameters.containsKey("updateToNow")) {
         m_updateToNow = Boolean.parseBoolean(parameters.getProperty("updateToNow"));
      }
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#assemble(java.io.Serializable, java.lang.Object)
    */
   public Object assemble(Serializable cached, Object owner) throws HibernateException {
      return cached;
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#deepCopy(java.lang.Object)
    */
   public Object deepCopy(Object object) throws HibernateException {
      if (object == null) return null;
      return new Date(((Date)object).getTime());
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#disassemble(java.lang.Object)
    */
   public Serializable disassemble(Object value) throws HibernateException {
      return (Serializable) value;
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#equals(java.lang.Object, java.lang.Object)
    */
   public boolean equals(Object x, Object y) throws HibernateException {
      if (x == y) return true;
      if (x == null || y == null) return false;
      return x.equals(y);
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#hashCode(java.lang.Object)
    */
   public int hashCode(Object object) throws HibernateException {
      return object.hashCode();
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#isMutable()
    */
   public boolean isMutable() {
      return true;
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
    */
   public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
      Date result = null;
      Calendar cal = new GregorianCalendar(TimeZone.getTimeZone(UTC_TZ));
      Timestamp timeStamp = resultSet.getTimestamp(names[0], cal);

      result = new Date(timeStamp.getTime());

      return result;
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
    */
   public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException {
      if (m_updateToNow) {
         value = new Date();
      }

      Calendar cal = new GregorianCalendar(TimeZone.getTimeZone(UTC_TZ));
      Timestamp x = new Timestamp(((Date)value).getTime());
      statement.setTimestamp(index, x, cal);
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#replace(java.lang.Object, java.lang.Object, java.lang.Object)
    */
   public Object replace(Object original, Object target, Object owner) throws HibernateException {
      if (m_updateToNow) {
         return new Date();
      } else {
         return original;
      }
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#returnedClass()
    */
   public Class returnedClass() {
      return Date.class;
   }

   /* (non-Javadoc)
    * @see org.hibernate.usertype.UserType#sqlTypes()
    */
   public int[] sqlTypes() {
      return new int[] { java.sql.Types.TIMESTAMP };
   }
}

1 个答案:

答案 0 :(得分:1)

在保存/更新实体以及必须设置查询参数时都会调用

nullSafeSet()

你的问题在于“updateToNow”标志;如果在给定实体的映射中将其设置为true,则始终将使用当前时间戳覆盖值。删除它,你会没事的。

如果您始终将时间戳设置为当前(对于给定列),请考虑在数据库中执行此操作并将属性映射为“已生成”。