Проблема с перечислениями и типом json в Hibernate - PullRequest
0 голосов
/ 06 июля 2018

Я использую Hibernate Framework на моей стороне сервера с Postgres в качестве серверной части. Я использую тип enum users.user_role (здесь пользователи - это схемы). Определение для ENUM

 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 для той же цели, выдается ошибка 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 type возникла та же проблема. Я пытался отправить тип String для JSON в PLSQL, но он показывает

Ошибка : ОШИБКА: столбец «данные» имеет тип json, но выражение имеет тип String

Настройка параметров, таких как

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

1 Ответ

0 голосов
/ 31 октября 2018

Решение работает для меня

Допустим, у меня есть enum типа 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.Сначала нам нужно создать enum в 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)})

Затем вам нужно добавить аннотацию для связи класса с типом enum, как в моем случае

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

Теперь вы можете сохранить эти данные в административной таблице, где admin_role имеетenum_type.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...