我有一個自定義的UserType,它將日期/時間值存儲在TIMESTAMP字段中,並在插入記錄時更新爲當前時間'UTC'或更新。 (此字段不用於版本控制或用於id目的)Hibernate UserType nullSafeSet - 如何知道是否調用插入/更新或選擇
問題是,這個工作原理非常好,但如果您需要運行查詢,此字段是準備好的語句生成時的條件之一,則自定義用戶類型調用nullSafeSet將值設置爲當前時間,以便查詢始終將該條件設置爲當前時間,而不會產生期望的結果。
是否有可能使nullSafeSet知道它被調用的上下文,以便它可以調整它的插入/更新或選擇的行爲。或者也許有另一種方法來做到這一點?
我試過使用<時間戳.../>,但它不寫入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
是的,這似乎是做到這一點的方法,但使用Derby,您需要使用CURRENT_TIMESTAMP或類似的字段。 Derby不支持針對特定時區(數據庫的UTC)的CURRENT_TIMESTAMP,僅針對虛擬機的當前時區,在我的情況下,該時區必須與UTC不同。 – 2009-09-25 04:55:06
那麼,您的其他選擇是在保存時或在適當的監聽器中使用DAO(如果您使用的是JPA/Hibernate實體管理器,則使用'@ PrePersist')。 – ChssPly76 2009-09-25 05:14:37
目前我剛剛完成了DAO中的更新。稍後我可能會重新訪問一個更好的解決方案。我在Google上搜索時看到了@PrePersist,似乎是一種可能的解決方案,但目前我還沒有使用註釋或JPA/HibernateEntityManager,並且需要很長時間才能滿足當前的需求。 – 2009-09-25 05:32:50