Я использую фреймворк гибернации на своей стороне сервера с 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, "[email protected]");
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.
Error : ERROR: column "user_role_type" is of type users.user_role but expression is of type 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 возникла такая же проблема. Я попытался отправить тип String для json в PLSQL, но он показывает
Error : ERROR: column "data" is of json but expression is of type String
Параметр настройки как
PGobject pGobject1 = new PGobject();
pGobject1.setType("json");
pGobject1.setValue(data); //here data is of type string
sqlQuery.setParameter("data", data);




Решение работает для меня
Скажем, у меня есть перечислимый тип 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 enum, нам нужно добавить один класс. Я дал имя 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;
}
}
Вам нужно добавить TypeDef, например @TypeDefs ({ @TypeDef (name = "EnumerationType", typeClass = EnumerationType.class) })
Затем вам нужно добавить аннотацию, чтобы связать класс с типом перечисления, как в моем случае
@Basic
@Enumerated(EnumType.STRING)
@Type(type = "EnumerationType")
Теперь вы можете сохранить эти данные в административной таблице, где admin_role имеет enum_type.
Уровни запутывания, такие как Hibernate, не поддерживают расширенные функции современных реляционных баз данных.