Hibernate中的枚举和json类型问题

时间:2018-07-06 11:04:18

标签: java postgresql hibernate enums

我在服务器端使用休眠框架,并以Postgres作为后端。我使用枚举类型users.user_role(这里的用户是一个架构)。 ENUM的定义是

 create type users.user_role as ENUM ('Agent', 'Customer');

现在,我正在使用“ org.postgresql.Driver”连接到数据库。为此,我正在使用postgressql-9.3-1101-jdbc4.jar。

当我尝试使用Prepared Statement插入值时,它的工作正常。正常工作的基本代码如下。

    String sqlQuery = "insert into users.user (user_id, created, last_modified, client_id, email, active, data, user_role_type) values (?, ?, ?, ?, ?, ?, ?, ?)";

    try {
        Class.forName("org.postgresql.Driver");

        Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/kc_abhi","postgres","root");

        PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery);

        preparedStatement.setObject(1, UUID.fromString("d70328f0-7301-4ce7-9c3d-64938f9c6c7d"));
        preparedStatement.setObject(2, new Timestamp(System.currentTimeMillis()));
        preparedStatement.setObject(3, new Timestamp(System.currentTimeMillis()));
        preparedStatement.setObject(4, UUID.fromString("4753fe2b-f0a6-4ee9-8cc9-8bb20b60ef73"));
        preparedStatement.setObject(5, "ab@everestek.com");
        preparedStatement.setObject(6, true);
        PGobject pGobject = new PGobject();
        pGobject.setType("json");
        pGobject.setValue("{\"data\":\"data\"}");
        preparedStatement.setObject(7, pGobject);
        PGobject pGobject1 = new PGobject();
        pGobject1.setType("user_role");
        pGobject1.setValue("Customer");
        preparedStatement.setObject(8, pGobject1);

        int i = preparedStatement.executeUpdate();

        System.out.println("i = " + i);

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    }

问题

当我出于相同目的尝试使用org.hibernate.SQLQuery时,会给出ENUM错误。

  

错误:错误:“ user_role_type”列的类型为users.user_role,但表达式的类型为bytea

查询

SQLQuery sqlQuery = currentSession().createSQLQuery("insert into users.user (user_id, created, last_modified, client_id, email, active, data, user_role_type, user_role_data) values (:userId, :created, :lastModified, :clientId, :email, :active, :data, :userRoleType, :userRoleData));

设置参数

    PGobject pGobject1 = new PGobject();
    pGobject1.setType("user_role");
    pGobject1.setValue("Customer");
    sqlQuery.setParameter("user_role_type", "Customer");

现在json类型发生了相同的问题。我尝试在PLSQL中为JSON发送String类型,但显示

  

错误:错误:“数据”列为json但表达式的类型为String

设置参数

    PGobject pGobject1 = new PGobject();
    pGobject1.setType("json");
    pGobject1.setValue(data); //here data is of type string
    sqlQuery.setParameter("data", data);

1 个答案:

答案 0 :(得分:0)

解决方案适合我

假设我的枚举类型为ADMIN和ORGANIZATION_ADMIN。所以我的查询就是这样

 create type admins.admin_role as enum ('ADMIN','ORGANIZATION_ADMIN');

 create table admins.admin (
    admin_id            uuid        not null,
    name                text        not null,
    first_name          text        not null,
    last_name           text        not null,
    admin_role          admins.admin_role,
    created             timestamp   not null,
    last_modified       timestamp   not null,
    created_by          uuid        not null references admins.admin(admin_id) deferrable initially deferred,
    last_modified_by    uuid        not null references admins.admin(admin_id) deferrable initially deferred,
    delete              boolean     not null default false,
    primary key (admin_id),
    constraint empty_name_check check ((length(name) >= 1) and (name not like 'null')),
    constraint empty_first_name_check check ((length(first_name) >= 1) and (name not like 'null')),
    constraint empty_last_name_check check ((length(last_name) >= 1) and (name not like 'null'))
    );

因此,要使用Java枚举类型对此进行映射,我们需要添加一个类。我给了名字EnumerationType,它扩展了org.hibernate.type.EnumType并定义了nullSafeSet方法。

我的EnumerationType.java如下

 package com.schoolmanager.postgres.type.enumeration;

 import org.hibernate.HibernateException;
 import org.hibernate.engine.spi.SessionImplementor;

 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Types;

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

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

 }

现在,当我不得不使用这种映射时,我需要添加TypeDefs。首先,我们需要在Java中创建枚举。

 public enum AdminRole {
    ADMIN("ADMIN"),
    ORGANIZATION_ADMIN("ORGANIZATION_ADMIN");

    private String value;

    AdminRole(String value) {
        this.value = value;
    }
}

然后我们可以如下使用它。

@Entity
@Table(schema = "admins", name = "admin", uniqueConstraints = @UniqueConstraint(columnNames={"adminId"}))
@TypeDefs({
    @TypeDef(name = "EnumerationType", typeClass = EnumerationType.class)
})
public class Admin {

private UUID adminId;
private String name;
private String firstName;
private String lastName;
private AdminRole adminRole;
private Date created;
private Date lastModified;
private UUID createdBy;
private UUID lastModifiedBy;
private boolean delete;


@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public UUID getAdminId() {
    return adminId;
}

public void setAdminId(UUID adminId) {
    this.adminId = adminId;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

@Basic
@Enumerated(EnumType.STRING)
@Type(type = "EnumerationType")
public AdminRole getAdminRole() {
    return adminRole;
}

public void setAdminRole(AdminRole adminRole) {
    this.adminRole = adminRole;
}

@Column(columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
@Temporal(TemporalType.TIMESTAMP)
public Date getCreated() {
    return created;
}

public void setCreated(Date created) {
    this.created = created;
}

@Column(columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
@Temporal(TemporalType.TIMESTAMP)
public Date getLastModified() {
    return lastModified;
}

public void setLastModified(Date lastModified) {
    this.lastModified = lastModified;
}

public UUID getCreatedBy() {
    return createdBy;
}

public void setCreatedBy(UUID createdBy) {
    this.createdBy = createdBy;
}

public UUID getLastModifiedBy() {
    return lastModifiedBy;
}

public void setLastModifiedBy(UUID lastModifiedBy) {
    this.lastModifiedBy = lastModifiedBy;
}

public boolean isDelete() {
    return delete;
}

public void setDelete(boolean delete) {
    this.delete = delete;
}
}

您需要添加TypeDefs,例如     @TypeDefs({         @TypeDef(name =“ EnumerationType”,typeClass = EnumerationType.class)     })

然后,您需要添加注释以将类与枚举类型相关联,就像我的情况一样

@Basic
@Enumerated(EnumType.STRING)
@Type(type = "EnumerationType")

现在您可以将此数据保存在admin_role为enum_type的管理表中。