gpt4 book ai didi

java - 如何使用 JPA 和 Hibernate 映射 PostgreSQL 枚举

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:44:03 24 4
gpt4 key购买 nike

我正在尝试将名为 transmission_result 的 PostgreSQL 自定义类型映射到 Hibernate/JPA POJO。 PostgreSQL 自定义类型或多或少是一种 enum 类型的字符串值。

我创建了一个名为 PGEnumUserType 的自定义 EnumUserType 以及一个代表 PostgreSQL 枚举值的 enum 类。当我针对真实数据库运行它时,我收到以下错误:

'ERROR: column "status" is of type transmission_result but expression is of type
character varying
Hint: You will need to rewrite or cast the expression.
Position: 135 '

看到这个后,我想我需要将我的 SqlTypes 更改为 Types.OTHER。但是这样做会破坏我的集成测试(在内存数据库中使用 HyperSQL)并显示消息:

'Caused by: java.sql.SQLException: Table not found in statement
[select enrollment0_."id" as id1_47_0_,
enrollment0_."tpa_approval_id" as tpa2_47_0_,
enrollment0_."tpa_status_code" as tpa3_47_0_,
enrollment0_."status_message" as status4_47_0_,
enrollment0_."approval_id" as approval5_47_0_,
enrollment0_."transmission_date" as transmis6_47_0_,
enrollment0_."status" as status7_47_0_,
enrollment0_."transmitter" as transmit8_47_0_
from "transmissions" enrollment0_ where enrollment0_."id"=?]'

我不确定为什么更改 sqlType 会导致此错误。感谢您的帮助。

JPA/Hibernate 实体:

@Entity
@Access(javax.persistence.AccessType.PROPERTY)
@Table(name="transmissions")
public class EnrollmentCycleTransmission {

// elements of enum status column
private static final String ACCEPTED_TRANSMISSION = "accepted";
private static final String REJECTED_TRANSMISSION = "rejected";
private static final String DUPLICATE_TRANSMISSION = "duplicate";
private static final String EXCEPTION_TRANSMISSION = "exception";
private static final String RETRY_TRANSMISSION = "retry";

private Long transmissionID;
private Long approvalID;
private Long transmitterID;
private TransmissionStatusType transmissionStatus;
private Date transmissionDate;
private String TPAApprovalID;
private String TPAStatusCode;
private String TPAStatusMessage;


@Column(name = "id")
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getTransmissionID() {
return transmissionID;
}

public void setTransmissionID(Long transmissionID) {
this.transmissionID = transmissionID;
}

@Column(name = "approval_id")
public Long getApprovalID() {
return approvalID;
}

public void setApprovalID(Long approvalID) {
this.approvalID = approvalID;
}

@Column(name = "transmitter")
public Long getTransmitterID() {
return transmitterID;
}

public void setTransmitterID(Long transmitterID) {
this.transmitterID = transmitterID;
}

@Column(name = "status")
@Type(type = "org.fuwt.model.PGEnumUserType" , parameters ={@org.hibernate.annotations.Parameter(name = "enumClassName",value = "org.fuwt.model.enrollment.TransmissionStatusType")} )
public TransmissionStatusType getTransmissionStatus() {
return this.transmissionStatus ;
}

public void setTransmissionStatus(TransmissionStatusType transmissionStatus) {
this.transmissionStatus = transmissionStatus;
}

@Column(name = "transmission_date")
public Date getTransmissionDate() {
return transmissionDate;
}

public void setTransmissionDate(Date transmissionDate) {
this.transmissionDate = transmissionDate;
}

@Column(name = "tpa_approval_id")
public String getTPAApprovalID() {
return TPAApprovalID;
}

public void setTPAApprovalID(String TPAApprovalID) {
this.TPAApprovalID = TPAApprovalID;
}

@Column(name = "tpa_status_code")
public String getTPAStatusCode() {
return TPAStatusCode;
}

public void setTPAStatusCode(String TPAStatusCode) {
this.TPAStatusCode = TPAStatusCode;
}

@Column(name = "status_message")
public String getTPAStatusMessage() {
return TPAStatusMessage;
}

public void setTPAStatusMessage(String TPAStatusMessage) {
this.TPAStatusMessage = TPAStatusMessage;
}
}

自定义枚举用户类型:

public class PGEnumUserType implements UserType, ParameterizedType {

private Class<Enum> enumClass;

public PGEnumUserType(){
super();
}

public void setParameterValues(Properties parameters) {
String enumClassName = parameters.getProperty("enumClassName");
try {
enumClass = (Class<Enum>) Class.forName(enumClassName);
} catch (ClassNotFoundException e) {
throw new HibernateException("Enum class not found ", e);
}

}

public int[] sqlTypes() {
return new int[] {Types.VARCHAR};
}

public Class returnedClass() {
return enumClass;
}

public boolean equals(Object x, Object y) throws HibernateException {
return x==y;
}

public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}

public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
String name = rs.getString(names[0]);
return rs.wasNull() ? null: Enum.valueOf(enumClass,name);
}

public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.VARCHAR);
}
else {
st.setString(index,((Enum) value).name());
}
}

public Object deepCopy(Object value) throws HibernateException {
return value;
}

public boolean isMutable() {
return false; //To change body of implemented methods use File | Settings | File Templates.
}

public Serializable disassemble(Object value) throws HibernateException {
return (Enum) value;
}

public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}

public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}

public Object fromXMLString(String xmlValue) {
return Enum.valueOf(enumClass, xmlValue);
}

public String objectToSQLString(Object value) {
return '\'' + ( (Enum) value ).name() + '\'';
}

public String toXMLString(Object value) {
return ( (Enum) value ).name();
}
}

枚举类:

public enum TransmissionStatusType {
accepted,
rejected,
duplicate,
exception,
retry}

最佳答案

如果您在 PostgreSQL 中有以下 post_status_info 枚举类型:

CREATE TYPE post_status_info AS ENUM (
'PENDING',
'APPROVED',
'SPAM'
)

您可以使用以下自定义 Hibernate 类型轻松地将 Java 枚举映射到 PostgreSQL 枚举列类型:

public class PostgreSQLEnumType extends org.hibernate.type.EnumType {

public void nullSafeSet(
PreparedStatement st,
Object value,
int index,
SharedSessionContractImplementor session)
throws HibernateException, SQLException {
if(value == null) {
st.setNull( index, Types.OTHER );
}
else {
st.setObject(
index,
value.toString(),
Types.OTHER
);
}
}
}

要使用它,您需要使用 Hibernate @Type 注释对该字段进行注释,如下例所示:

@Entity(name = "Post")
@Table(name = "post")
@TypeDef(
name = "pgsql_enum",
typeClass = PostgreSQLEnumType.class
)
public static class Post {

@Id
private Long id;

private String title;

@Enumerated(EnumType.STRING)
@Column(columnDefinition = "post_status_info")
@Type( type = "pgsql_enum" )
private PostStatus status;

//Getters and setters omitted for brevity
}

就是这样,它就像一个魅力。这是一个 test on GitHub that proves it .

关于java - 如何使用 JPA 和 Hibernate 映射 PostgreSQL 枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7603500/

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