【问题标题】:Postgres enum with Java Enum in Play Framework在 Play 框架中使用 Java 枚举的 Postgres 枚举
【发布时间】:2023-04-04 02:10:01
【问题描述】:

我尝试在 Play Framework 2.5.0 中使用带有 Hibernate/JPA 的 postgres 自定义枚举。

所以基本上我添加了一个自定义 UserType 并添加了一个指向特定 java 类型/转换器的 @Type 注释。另外,我尝试使用 JPA 2.1 @Convert 和 @Converter 注释。我对 @Enumerated 和 @Type (org.hibernate.type.EnumType) 注释做了同样的事情。但是,其中任何一个都不适合我!

似乎注释没有重新整理,因为在 printstacktrace 中我看不到转换和类型类。

SQL 代码

CREATE TYPE auth_service_provider AS ENUM ('faceboook', 'google', 'linkedin', 'twitter');

CREATE TABLE "auth"(
   ...
   "auth_service" auth_service_provider NOT NULL,
   "auth_username" VARCHAR(128) NOT NULL,
   ...
);

授权实体

@Entity
@Table(name = "auth", schema = "public", uniqueConstraints = @UniqueConstraint(columnNames = { "auth_id","user_refid" }) )
public class Auth implements java.io.Serializable {

public static enum AuthServiceProvider {
    @JsonProperty("google")     google,
    @JsonProperty("twitter")    twitter,
    @JsonProperty("facebook")   facebook,
    @JsonProperty("linkedin")   linkedin;
};

@Convert(converter = AuthServiceConverter.class)
//@Type(type="AuthServiceType") 
//@Enumerated(EnumType.STRING)
//@Type(type = "org.hibernate.type.EnumType",
//parameters = {
//        @Parameter(name  = "enumClass", value = "AuthServiceType"),
//        @Parameter(name = "type", value = "1111"),
//        @Parameter(name = "useNamed", value = "true")
//})
private AuthServiceProvider authService;
private String authUsername;

...
//getters and setters
}

AuthServiceType

public class AuthServiceType implements UserType,Serializable { 

private static final long serialVersionUID = 4378790812145778372L;

private static final int[] SQL_TYPES = new int[]{Types.OTHER};

@Override
public int[] sqlTypes() {
    return SQL_TYPES;
}

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

@Override
public Object deepCopy(Object value) throws HibernateException {

    if (value == null) return value;
    try {
        return AuthServiceProvider.valueOf(((AuthServiceProvider)value).name());
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

@Override
public Serializable disassemble(Object value) throws HibernateException {
    return ((AuthServiceProvider)value).toString();
}

@Override
public boolean equals(Object x, Object y) throws HibernateException {
        if(x == y)
            return true;
        if(x == null || y == null)
            return false;
        return ((AuthServiceProvider) x).name() == ((AuthServiceProvider) y).name();
}

@Override
public int hashCode(Object value) throws HibernateException {
    return ((AuthServiceProvider)value).toString().hashCode();
}

@Override
public boolean isMutable() {
    return true;
}

@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
        throws HibernateException, SQLException {
    Logger.debug("nullSafeGet: name {}",names[0]);

    if (rs.wasNull()) {
        return null;
    }

    Object identifier = rs.getObject(names[0]);

    if (identifier instanceof PGobject) {eturn getValueOfMethod().invoke(getMappedClass(), new Object[] { (PGobject) identifier).getValue() });
        return AuthServiceProvider.valueOf(((PGobject) identifier).getValue());
    } else {
        throw new IllegalArgumentException("AuthServiceType expected PGobject, received " + identifier.getClass().getName() + " with value of '" + identifier + "'");
    }

}

@Override
public void nullSafeSet(PreparedStatement stmt, Object value, int index, SessionImplementor session)
        throws HibernateException, SQLException {
    Logger.debug("nullSafeSet: value {}",value);
    if (value == null) {
        stmt.setNull(index, SQL_TYPES[0]);
    } else {
        PGobject pg = new PGobject();
        pg.setType("auth_service_provider");
        try {
            pg.setValue( value.toString() );
        } catch (SQLException e) {
            throw new IllegalArgumentException("Value not expected for PGobject: "+value.toString(),e);
        }
        stmt.setObject(index, pg,SQL_TYPES[0]);
    }
}


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

@Override
@SuppressWarnings("unchecked")
public Class returnedClass() {
    return AuthServiceProvider.class;
}

}

AuthServiceConverter

@Converter
public class AuthServiceConverter implements AttributeConverter<AuthServiceProvider,PGobject> {

@Override
public PGobject convertToDatabaseColumn(AuthServiceProvider value) {
    Logger.debug("convertToDatabase");
    PGobject pg = new PGobject();
    pg.setType("auth_service_provider");
    try {
        pg.setValue( value.toString() );
    } catch (SQLException e) {
        throw new IllegalArgumentException("Value not expected for PGobject: "+value.toString(),e);
    }
    return pg;
}

@Override
public AuthServiceProvider convertToEntityAttribute(PGobject value) {
    Logger.debug("convertToEntityAttribute");
    return AuthServiceProvider.valueOf(value.getValue().toUpperCase());
}


}

例外

Caused by: org.postgresql.util.PSQLException: ERROR: column "auth_service" is of type auth_service_provider but expression is of type integer
Hint: You will need to rewrite or cast the expression.
Position: 134

编辑

我发现了错误。我在字段声明中有@Type 注释,在getter 方法中有@Column 注释。 EnumType 和 Converts 不起作用,但是 Hibernate @Type 注释起作用了,所以注释应该写在我的 getter 方法中加入 @Column 注释。

示例

@Column(name = "auth_service", nullable = false)
@Type(type="AuthServiceType")
public AuthServiceProvider getAuthService() {
    return this.authService;
}

【问题讨论】:

    标签: hibernate postgresql jpa playframework enums


    【解决方案1】:

    试试

    @Column(columnDefinition="auth_service_provider")
    @ColumnTransformer(read="auth_service::varchar", write="?::auth_service_provider")
    @Enumerated(EnumType.STRING)
    private AuthServiceProvider authService;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多