如何使用 Spring Data JPA 映射实体中的 Oracle 对象类型?
How to map Oracle Object type in an entity using Spring Data JPA?
此问题与使用 Spring Data JPA 在实体中映射 Oracle 对象类型特别相关。 other question 没有帮助详细说明问题。
下面是详细信息:
我在 Spring Data JPA Reference 和任何其他搜索结果中都找不到与使用 Spring Data JPA 在实体对象中映射 Oracle 对象类型相关的信息。
场景:
假设我有以下 date_typ Oracle 类型。
CREATE TYPE date_typ AS OBJECT (
month VARCHAR2(2),
day VARCHAR2(2),
year VARCHAR2(4),
extension VARCHAR2(10),
MEMBER FUNCTION getFullDate RETURN VARCHAR2
);
CREATE TYPE BODY date_typ AS
MAP MEMBER FUNCTION getFullDate RETURN VARCHAR2 AS
BEGIN
return month || day || year;
END getFullDate;
END;
现在在oracle数据库中table,说REGISTRATION,其中一列是上面的date_typ
Column Type
REG_ID VARCHAR2(25) primary key
FIRSTNAME VARCHAR2(30) not null
LASTNAME VARCHAR2(30) not null
MIDDLEINIT VARCHAR2(10)
REQUESTEDDATE DATE_TYP
...
...
现在,我需要映射实体中的上述列
@Entity
@Table(name = "REGISTRATION", schema = "accounts")
public class RegistrationEntity {
@Id
@Column(name = "REG_ID")
private String registrationId;
@Column(name = "FIRSTNAME", nullable = false)
private String firstName;
@Column(name = "LASTNAME", nullable = false)
private String lastName;
@Column(name = "MIDDLEINIT")
private String middleInitial;
requestedDate ???
}
如何将 requestedDate
映射到 [=42= 中的 DATE_TYP(oracle 对象类型)的 REQUESTEDDATE
列] JPA?
注意:我正在使用 Hibernate 作为持久性提供程序。
This answer states, that there is no official support in JPA for Oracles Object Types, but support for it in Eclipse Link。我想这意味着 Hibernate 中没有开箱即用的支持。
Spring数据并没有真正参与其中,因为它只是使用 JPA 实现将实体映射到数据库。 Spring 数据提供的转换和预测仅转换输入 parameters/output 值,然后再将它们传递给/从 JPA 提供程序获取它们。
这是我的实现,使用了 Jens Schauder 提供的 link 的更新版本。 link 中描述的实现使用了已弃用的类型 STRUCT,并且对我来说并不适用。这对我有用。
自定义对象类型
create type CUSTOMER_ADDRESS as object
(
STREET_ADDRESS VARCHAR2(50),
CITY VARCHAR2(20)
)
import lombok.Data;
@Data
public class Address {
String streetAddress;
String city;
}
自定义类型:
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
import java.io.Serializable;
import java.sql.*;
import static java.sql.Types.STRUCT;
/**
* **
* Usage in Entity
* @Column(name="TABLE_NAME", columnDefinition="CUSTOMER_ADDRESS")
* @Type(type= "com.example.demo.AddressType")
* private Address address;
*/
public class AddressType implements UserType {
private static final int SQL_TYPE = STRUCT;
private static final String DB_OBJECT_TYPE = "CUSTOMER_ADDRESS"; //DB custom type name
@Override
public int[] sqlTypes() {
return new int[]{SQL_TYPE};
}
@Override
public Class returnedClass() {
return Address.class;
}
@Override
public Address nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
final Struct struct = (Struct) rs.getObject(names[0]);
if (rs.wasNull()) {
return null;
}
final Address address = new Address();
address.streetAddress = (String) struct.getAttributes()[0];
address.city = (String) struct.getAttributes()[1];
return address;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
if (value != null) {
final Address address = (Address) value;
final Struct address = st.getConnection().createStruct(DB_OBJECT_TYPE,new Object[]{
address.streetAddress,
address.city
});
st.setObject(index, address, SQL_TYPE);
} else {
st.setNull(index, SQL_TYPE, DB_OBJECT_TYPE);
}
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ((x == y) || (x != null && y != null && x.equals(y)));
}
@Override
public int hashCode(Object x) throws HibernateException {
return x != null ? x.hashCode() : 0;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value == null ? null : value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
Object deepCopy = deepCopy(value);
if (!(deepCopy instanceof Serializable)) {
return (Serializable) deepCopy;
}
return null;
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return deepCopy(cached);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return deepCopy(original);
}
}
此问题与使用 Spring Data JPA 在实体中映射 Oracle 对象类型特别相关。 other question 没有帮助详细说明问题。
下面是详细信息:
我在 Spring Data JPA Reference 和任何其他搜索结果中都找不到与使用 Spring Data JPA 在实体对象中映射 Oracle 对象类型相关的信息。
场景:
假设我有以下 date_typ Oracle 类型。
CREATE TYPE date_typ AS OBJECT (
month VARCHAR2(2),
day VARCHAR2(2),
year VARCHAR2(4),
extension VARCHAR2(10),
MEMBER FUNCTION getFullDate RETURN VARCHAR2
);
CREATE TYPE BODY date_typ AS
MAP MEMBER FUNCTION getFullDate RETURN VARCHAR2 AS
BEGIN
return month || day || year;
END getFullDate;
END;
现在在oracle数据库中table,说REGISTRATION,其中一列是上面的date_typ
Column Type
REG_ID VARCHAR2(25) primary key
FIRSTNAME VARCHAR2(30) not null
LASTNAME VARCHAR2(30) not null
MIDDLEINIT VARCHAR2(10)
REQUESTEDDATE DATE_TYP
...
...
现在,我需要映射实体中的上述列
@Entity
@Table(name = "REGISTRATION", schema = "accounts")
public class RegistrationEntity {
@Id
@Column(name = "REG_ID")
private String registrationId;
@Column(name = "FIRSTNAME", nullable = false)
private String firstName;
@Column(name = "LASTNAME", nullable = false)
private String lastName;
@Column(name = "MIDDLEINIT")
private String middleInitial;
requestedDate ???
}
如何将 requestedDate
映射到 [=42= 中的 DATE_TYP(oracle 对象类型)的 REQUESTEDDATE
列] JPA?
注意:我正在使用 Hibernate 作为持久性提供程序。
This answer states, that there is no official support in JPA for Oracles Object Types, but support for it in Eclipse Link。我想这意味着 Hibernate 中没有开箱即用的支持。
Spring数据并没有真正参与其中,因为它只是使用 JPA 实现将实体映射到数据库。 Spring 数据提供的转换和预测仅转换输入 parameters/output 值,然后再将它们传递给/从 JPA 提供程序获取它们。
这是我的实现,使用了 Jens Schauder 提供的 link 的更新版本。 link 中描述的实现使用了已弃用的类型 STRUCT,并且对我来说并不适用。这对我有用。
自定义对象类型
create type CUSTOMER_ADDRESS as object
(
STREET_ADDRESS VARCHAR2(50),
CITY VARCHAR2(20)
)
import lombok.Data;
@Data
public class Address {
String streetAddress;
String city;
}
自定义类型:
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
import java.io.Serializable;
import java.sql.*;
import static java.sql.Types.STRUCT;
/**
* **
* Usage in Entity
* @Column(name="TABLE_NAME", columnDefinition="CUSTOMER_ADDRESS")
* @Type(type= "com.example.demo.AddressType")
* private Address address;
*/
public class AddressType implements UserType {
private static final int SQL_TYPE = STRUCT;
private static final String DB_OBJECT_TYPE = "CUSTOMER_ADDRESS"; //DB custom type name
@Override
public int[] sqlTypes() {
return new int[]{SQL_TYPE};
}
@Override
public Class returnedClass() {
return Address.class;
}
@Override
public Address nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
final Struct struct = (Struct) rs.getObject(names[0]);
if (rs.wasNull()) {
return null;
}
final Address address = new Address();
address.streetAddress = (String) struct.getAttributes()[0];
address.city = (String) struct.getAttributes()[1];
return address;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
if (value != null) {
final Address address = (Address) value;
final Struct address = st.getConnection().createStruct(DB_OBJECT_TYPE,new Object[]{
address.streetAddress,
address.city
});
st.setObject(index, address, SQL_TYPE);
} else {
st.setNull(index, SQL_TYPE, DB_OBJECT_TYPE);
}
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ((x == y) || (x != null && y != null && x.equals(y)));
}
@Override
public int hashCode(Object x) throws HibernateException {
return x != null ? x.hashCode() : 0;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value == null ? null : value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
Object deepCopy = deepCopy(value);
if (!(deepCopy instanceof Serializable)) {
return (Serializable) deepCopy;
}
return null;
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return deepCopy(cached);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return deepCopy(original);
}
}