代码之家  ›  专栏  ›  技术社区  ›  Abhishek

hibernate中的枚举和json类型有问题

  •  0
  • Abhishek  · 技术社区  · 6 年前

    我在服务器端使用hibernate框架,后端是postgres。我使用枚举类型 users.user_role (这里用户是一个模式)。 枚举的定义是

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

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

    当我试图使用准备好的语句插入值时,它的工作正常。工作正常的基本代码如下所示。

        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用于相同的目的时,它给出了枚举的错误。

    错误 :错误:“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的字符串类型,但是它显示

    错误 :error:列“data”为json,但表达式为string类型

    设置参数类似

        PGobject pGobject1 = new PGobject();
        pGobject1.setType("json");
        pGobject1.setValue(data); //here data is of type string
        sqlQuery.setParameter("data", data);
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   Abhishek    6 年前

    解决问题的工作是给我的

    假设我有枚举类型管理和组织管理。所以我的问题是这样的

     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);
             }
         }
    
     }
    

    现在当我必须使用这种映射时,我需要添加typedef。首先我们需要在java中创建enum。

     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;
    }
    }
    

    你需要添加typedef,比如 @类型定义({ @typedef(name=“EnumerationType”,typeClass=EnumerationType.Class) })

    然后您需要添加注释来将类与枚举类型关联起来,就像在我的例子中一样

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

    现在您可以将此数据保存在管理表中,其中管理角色是枚举类型。