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

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

问题描述

我们有一个带有postgres枚举的postgres数据库.我们正在开始将JPA构建到我们的应用程序中.我们也有Java枚举,它反映了postgres枚举.现在最大的问题是如何使JPA一方面了解Java枚举,另一方面了解Postgres枚举? Java方面应该相当简单,但是我不确定如何进行postgres方面.

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.

推荐答案

这涉及到多个映射.

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

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)

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

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



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

然后,结果集将包含类型为"mood"且值为"happy"的PGObject,该列具有此枚举类型,而行的值为"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'.

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

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;

}

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

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;

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

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天全站免登陆