我们公司在一项老项目中使用了Java 7、Hibernate 3 和 Spring 3。所有的Spring和Hibernate配置都在XML文件中,不使用注解。
对于一些客户,数据库是Oracle,而对于其他客户,则是DB2。
在Oracle数据库中,当数据类型为Date且带有时间时,我们使用java.util.Date会遇到问题。问题出现在Hibernate准备查询时的绑定级别。
java.util.Date被转换为java.sql.Timestamp,最终绑定到oracle.sql.TIMESTAMP上。
我们的列具有oracle.sql.DATE类型,因此在Oracle中需要进行隐式转换以执行查询,导致索引无法使用。
我们的解决方案是在Oracle数据库中使用Hibernate的UserTypes将java Date转换为Oracle Date。
但正如我所说,我们使用XML配置,在使用Hibernate与Spring Jpa时,我找不到@Type注释的XML配置。
以下是具有Date类型logindate的person类的代码:
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.util.Date;
public class Person {
private Integer id;
private String fullName;
// @Type(type = "mypackage.OracleDate")
private Date loginDate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public Date getLoginDate() {
return loginDate;
}
public void setLoginDate(Date loginDate) {
this.loginDate = loginDate;
}
}
OracleDate用户类型的代码:
public class OracleDate implements UserType {
private static final int[] SQL_TYPES = new int[] {
Types.TIMESTAMP
};
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
@Override
public Class returnedClass() {
return Date.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y) {
return true;
}
if (x == null || y == null) {
return false;
}
Date dtx = (Date) x;
Date dty = (Date) y;
return dtx.equals(dty);
}
@Override
public int hashCode(Object o) throws HibernateException {
return o.hashCode();
}
@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
Object timestamp = StandardBasicTypes.TIMESTAMP.nullSafeGet(resultSet, names, null, owner);
if (resultSet.wasNull())
return null;
if (timestamp == null) {
return null;
}
Date ts = (Date) timestamp;
return ts;
}
@Override
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException {
if (value == null) {
StandardBasicTypes.TIMESTAMP.nullSafeSet(preparedStatement, null, index);
} else {
Date ldt = ((Date) value);
preparedStatement.setObject(index, new DATE(new Timestamp(ldt.getTime())));
}
}
JPA Bean:
<bean id="hostEntityManager"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="persistenceUnitManager" ref="persistenceUnitManager"></property>
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations" value="
classpath:PREPAID.CFG/DA.JPA/PERSISTENCE-ENTITIES/persistence.xml/>
<property name="persistenceUnitPostProcessors">
<bean class="mypackage.MergingPersistenceUnitPostProcessor" />
</property>
<property name="defaultDataSource" ref="dataSource"></property>
</bean>
persistence.xml文件:
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd ">
<persistence-unit name="system_persistence_unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<mapping-file>TESTAPPLICATION/CFG/DA/JPA/PERSISTENCE-ENTITIES/person.xml</mapping-file>
<class>mypackage.Person</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="show_sql" value="true"/>
<property name="hibernate.archive.autodetection" value="class" />
</properties>
</persistence-unit>
实体映射文件:
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
version="2.0">
<entity class="mypackage.Person">
<table name="Person" />
<named-query name="findLoginsByDate">
<query>select p from Person as p where p.loginDate >= :date </query>
</named-query>
<attributes>
<id name="id">
<column name="id" />
</id>
<basic name="fullName">
<column name="username" />
</basic>
<basic name="loginDate" >
<column name="loginDate" />
</basic>
</attributes>
</entity>
首先,我想知道使用usertype是否是处理我的问题的最佳解决方案?
还有,TypeDef和Type注释的xml配置是什么?