使用JPA,可以将关系表映射到java.util.Map作为@Entity吗?

时间:2013-11-18 14:22:27

标签: java hibernate jpa orm

关于问题

我第一次在这里提问,所以我想弄明白我的问题。我询问如何使用java.util.Map映射关系,也不使用java.util.Map作为@Embedded对象。我真正想知道的是使用java.util.Map作为映射的@Entity

的可能性

样本总是好于数千个单词。这就是我想要的简短内容:

<entity class="java.util.HashMap" access="KEY">
    <table name="TABLE_1"/>
    <attributes>
        <id name="id">
            <column name="COL_ID" />
        </id>
        <basic name="attr1" >
            <column name="COL_1" />
        </basic>
        <basic name="attr2" >
            <column name="COL_2" />
            <temporal>DATE</temporal>
        </basic>
        ...
    </attributes>
</entity>

如上所述,关系表TABLE_1的内容映射到类java.util.HashMap,其中:

  • 每个列名称都映射到在地图中存储为key的属性
  • 并且该列的值将value存储在与列key相关联的地图中

换句话说(较短的版本):

  • 表格列名称=&gt;地图键
  • 表格列值=&gt;地图值

在Java中,它会是这样的:

@Entity(name="TABLE_1")
public class View extends HashMap<String, Object> {
    // no attributes here because the columns will be mapped as key of this class

    // and the value type here is Object because the type of the columns can be anything (i.e. varchar, integer, timestamp etc.)
}

我知道这不是典型的ORM映射,它可能根本不是JPA的目的。但这是我用例中首先想到的。

用例

我们有一个带有一杯表的关系数据库,我们还根据这些表定义了一些视图。我们现在要做的是开发一个基于Web的UI来处理数据库中定义的视图。

或多或少“棘手”的事情是视图的定义尚未完成,我们肯定需要在将来修改和/或添加更多视图。但业务要求保持不变:允许用户查询,过滤和编辑视图,最终执行其他操作(例如审计,添加注释)。

在这种情况下,我们需要能够通过配置向应用程序添加/删除视图,并使用通用方法处理可在不同视图上使用的一组操作。部分解决方案是使用一个通用容器来保存数据,这些数据模糊了“视图真正是什么”。从哪里开始使用java.util.Map

我正在寻找在我们的用例中使用JPA映射的原因是能够使用更加代码友好的标准API,类型转换并避免使用可能难以维护的低级JDBC代码。

帮助

我的问题的任何答案和对我们的用例中使用的方法的其他建议都表示赞赏。

[已编辑]解决方案(以Alan Hay的建议)

使用Hibernate的 Dynamic models 功能,我可以轻松执行以下操作:

<hibernate-mapping>
    <!-- Specify the 'entity-name' instead of 'class' here to activate the dynamic model -->
    <class entity-name="DynamicEntity" table="TABLE1">
        <id name="id" column="COL_ID" type="long" />
        <property name="attribute1" column="COL_1" type="string" />
        <property name="attribute2" column="COL_2" type="string" />
        <property name="attribute3" column="COL_3" type="date" />
    </class>
</hibernate-mapping>

然后Hibernate会顺利处理所有事情:

Session hibernateSession = ...;
Map dynamicEntity = (Map) hibernateSession.get("DynamicEntity", 1L);
System.out.println(dynamicEntity.getClass());
System.out.println(dynamicEntity);

// output
// class java.util.HashMap
// {$type$=DynamicEntity, id=1, attribute1=foo, attribute2=bar, attribute3=2013-11-19}

2 个答案:

答案 0 :(得分:1)

是和否。 JPA规范中没有任何内容,但如果您使用的是Hibernate,那么Hibernate的“动态模型”功能似乎正是您所期待的:

http://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-dynamicmodels.html

答案 1 :(得分:0)

不,你不能用java.util.Map做到这一点,因为它只是一个界面。另外使用HashMap你不能这样做,因为它没有ID列(除了其他问题)。但是您可以创建一个包含MapEntity的实体private Map internalMap;并实现Map接口,在internalMap的每个接口中操纵包含的Map ,获得类似的结果。有了这个想法,我不知道后果是什么,当MapEntity用于其他实体时,但可能你不应该遇到任何问题。

示例(在这种情况下,视图为@Embeddable。如果视图是实体,请使用@MapKey注释

public class MapEntity implements Map<Integer, View> {


    //add the id column...


    @ElementCollection//+other mapping configuration like @CollectionTable (name = "ViewMap", joinColumns = @JoinColumn (name = "view_id"))
    private Map<Integer, View> internalMap = new HashMap<Integer, View>;


    //implementation of a method from the Map interface. The other methods are simply delegated to the internalmap.
    @Override
    public View put(Integer key, View value) {
      internalMap.put(key, value);
    }

}