Java 枚举、JPA 和 Postgres 枚举 - 如何让它们协同工作? [英] Java Enums, JPA and Postgres enums - How do I make them work together?

查看:20
本文介绍了Java 枚举、JPA 和 Postgres 枚举 - 如何让它们协同工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个带有 postgres 枚举的 postgres 数据库.我们开始将 JPA 构建到我们的应用程序中.我们也有反映 postgres 枚举的 Java 枚举.现在最大的问题是如何让 JPA 一方面理解 Java 枚举,另一方面理解 postgres 枚举?Java 方面应该相当简单,但我不知道如何做 postgres 方面.

解决方案

这涉及制作多个映射.

首先,JDBC 驱动程序返回 Postgres 枚举作为 PGObject 类型的实例.它的 type 属性具有您的 postgres 枚举的名称,以及 value 属性的值.(然而,序数并未存储,因此从技术上讲,它不再是枚举,因此可能完全没用)

无论如何,如果你在 Postgres 中有这样的定义:

<前><代码>CREATE TYPE情绪为ENUM('sad', 'ok', 'happy');

然后,结果集将包含一个类型为mood"、值为happy"的 PGObject,用于具有此枚举类型的列和值为happy"的行.

接下来要做的是编写一些拦截器代码,该代码位于 JPA 从原始结果集读取和设置实体值之间的位置.例如.假设您在 Java 中有以下实体:

<前><代码>公共@Entity 类人{公共静态枚举心情 {悲伤,好的,快乐}@Id 长 ID;心情心情;}

不幸的是,JPA 没有提供一个简单的拦截点,您可以在其中进行从 PGObject 到 Java 枚举 Mood 的转换.然而,大多数 JPA 供应商对此都有一些专有支持.例如,Hibernate 有 TypeDef 和 Type 注释(来自 Hibernate-annotations.jar).

<前><代码>@TypeDef(name="myEnumConverter", typeClass=MyEnumConverter.class)公共@Entity 类人{公共静态枚举心情 {悲伤,好的,快乐}@Id 长 ID;@Type(type="myEnumConverter") 心情心情;

这些允许您提供执行实际转换的 UserType 实例(来自 Hibernate-core.jar):

<前><代码>公共类 MyEnumConverter 实现 UserType {private static final int[] SQL_TYPES = new int[]{Types.OTHER};public Object nullSafeGet(ResultSet arg0, String[] arg1, Object arg2) 抛出 HibernateException, SQLException {对象 pgObject = arg0.getObject(X);//X 是包含枚举的列尝试 {方法 valueMethod = pgObject.getClass().getMethod("getValue");字符串值 = (String)valueMethod.invoke(pgObject);返回 Mood.valueOf(value);}捕获(异常 e){e.printStackTrace();}返回空;}公共 int[] sqlTypes() {返回 SQL_TYPES;}//其余方法省略}

这不是一个完整的工作解决方案,而只是一个指向正确方向的快速指针.

We have a postgres DB with postgres enums. We are starting to build JPA into our application. We also have Java enums which mirror the postgres enums. Now the big question is how to get JPA to understand Java enums on one side and postgres enums on the other? The Java side should be fairly easy but I'm not sure how to do the postgres side.

解决方案

This involves making multiple mappings.

First, a Postgres enum is returned by the JDBC driver as an instance of type PGObject. The type property of this has the name of your postgres enum, and the value property its value. (The ordinal is not stored however, so technically it's not an enum anymore and possibly completely useless because of this)

Anyway, if you have a definition like this in Postgres:


CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');

Then the resultset will contain a PGObject with type "mood" and value "happy" for a column having this enum type and a row with the value 'happy'.

Next thing to do is writing some interceptor code that sits between the spot where JPA reads from the raw resultset and sets the value on your entity. E.g. suppose you had the following entity in Java:


public @Entity class Person {

  public static enum Mood {sad, ok, happy}

  @Id Long ID;
  Mood mood;

}

Unfortunately, JPA does not offer an easy interception point where you can do the conversion from PGObject to the Java enum Mood. Most JPA vendors however have some proprietary support for this. Hibernate for instance has the TypeDef and Type annotations for this (from Hibernate-annotations.jar).


@TypeDef(name="myEnumConverter", typeClass=MyEnumConverter.class)
public @Entity class Person {

  public static enum Mood {sad, ok, happy}

  @Id Long ID;
  @Type(type="myEnumConverter") Mood mood;

These allow you to supply an instance of UserType (from Hibernate-core.jar) that does the actual conversion:


public class MyEnumConverter implements UserType {

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

    public Object nullSafeGet(ResultSet arg0, String[] arg1, Object arg2) throws HibernateException, SQLException {

        Object pgObject = arg0.getObject(X); // X is the column containing the enum

        try {
            Method valueMethod = pgObject.getClass().getMethod("getValue");
            String value = (String)valueMethod.invoke(pgObject);            
            return Mood.valueOf(value);     
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

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

    // Rest of methods omitted

}

This is not a complete working solution, but just a quick pointer in hopefully the right direction.

这篇关于Java 枚举、JPA 和 Postgres 枚举 - 如何让它们协同工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆