gpt4 book ai didi

java - 在带有 Spring Data JPA 的 hibernate 中使用 xml 配置而不是 @Type 注释

转载 作者:行者123 更新时间:2023-12-03 02:28:50 25 4
gpt4 key购买 nike

我的公司在其遗留项目之一中使用java 7hibernate 3以及spring 3。所有 spring 和 hibernate 配置都在 xml 文件中,并且不使用注释。

对于某些客户来说,数据库是oracle,对于其他客户来说,数据库是db2

在oracle中,当数据类型为Date并且我们使用java.util.date和时间时,我们会遇到问题。当 Hibernate 准备查询时,问题出现在绑定(bind)级别。

java.util.Date 转换为 java.sql.Timestamp,最终绑定(bind)到 oracle.sql.TIMESTAMP。

我们的列具有 oracle.sql.DATE 类型,因此 Oracle 中存在隐式转换来执行查询,导致索引无法使用。

我们的解决方案是在 hibernate 中使用 UserTypes 将 java Date 转换为 Oracle 数据库中的 Oracle Date。

但正如我所说,我们使用 xml 配置,并且在将 hibernate 与 spring Jpa 一起使用时找不到 @Type 注释的 xml 配置。

具有日期类型的登录日期的人员类的代码:

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 和类型注释的 xml 配置是什么?

最佳答案

At first I want know Is using usertype the best solution for handling my problem?

在给定的情况下,当您将日期与时间一起存储并且别无选择只能将其存储在 DATE 中时,它可能是。 (请注意,像 this 这样的一些资源表示使用 TIMESTAMP 应该没问题,而且它甚至不会产生更大的索引。)

And what's the xml config for TypeDef and Type annotations?

如果不能在实体上使用注解,我今天只能看到以下可能性:

A) 使用标准 Hibernate 映射 XML

先决条件:您必须将 JPA XML 映射迁移到 Hibernate native 格式。

将此添加到您的共享映射 XML:

<typedef class="com.company.OracleDate" name="OracleDate" />

然后在实体映射 XML 中引用您的自定义类型:

<property name="loginDate" type="OracleDate" />

An in-depth article

B) 尝试使用 JPA 2.1 中的属性转换器

前提条件:您必须迁移到 Hibernate 4.3 或更高版本(请参阅 compatibility matrix )并将 JPA 2.0 配置文件迁移到 2.1。

您需要实现 JPA 的 AttributeConverter 接口(interface),而不是实现 Hibenate 的 UserType。非常相似,这次您只需要实现 2 个方法:DbType ConvertToDatabaseColumn(JavaType value)JavaType ConvertToEntityAttribute(DbType value)

之后,在实体映射 XML 中引用转换器:

<convert converter="com.company.OracleDateConverter" attribute-name="loginDate" />

An in-depth article, uses annotations ,
SO question, uses XML

关于java - 在带有 Spring Data JPA 的 hibernate 中使用 xml 配置而不是 @Type 注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58833993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com