我有一个自定义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 classDateTimestampUserType
implements a Hibernate *UserType
to allow the persistence ofDate * instances as a TIMESTAMP in the database. * * All
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 }; } }Date
instances persisted are in UTC/GMT time. * * ThisUserType
implementation also allows for a boolean parameter * 'updateToNow' specified as part of Hibernate configuration. This parameter * controls whether when a Date
答案 0 :(得分:1)
nullSafeSet()
。
你的问题在于“updateToNow”标志;如果在给定实体的映射中将其设置为true,则始终将使用当前时间戳覆盖值。删除它,你会没事的。
如果您始终将时间戳设置为当前(对于给定列),请考虑在数据库中执行此操作并将属性映射为“已生成”。