用户使用Hibernate实现EAV模式 - >设置关系 [英] Implementing EAV pattern with Hibernate for User -> Settings relationship

查看:134
本文介绍了用户使用Hibernate实现EAV模式 - >设置关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Java / Spring MVC和Hibernate在我的web应用程序中设置一个简单的EAV模式。我似乎无法弄清楚这种场景下hibernate XML设置背后的魔力。



我的数据库表SETUP有三列:




  • user_id(FK)
  • setup_item

  • setup_value



数据库组合键由 user_id | setup_item



以下是Setup.java类:

  public class Setup实现CommonFormElements,Serializable {
private Map data = new HashMap();
private String saveAction;
private Integer speciesNamingList;
私人用户用户;

Logger log = LoggerFactory.getLogger(Setup.class);

public String getSaveAction(){
return saveAction;
}

public void setSaveAction(String action){
this.saveAction = action;
}

public User getUser(){
return user;
}

public void setUser(User user){
this.user = user;
}

public Integer getSpeciesNamingList(){
return speciesNamingList;
}

public void setSpeciesNamingList(Integer speciesNamingList){
this.speciesNamingList = speciesNamingList;
}

public Map getData(){
return data;
}

public void setData(Map data){
this.data = data;
}
}

Hibernate设置的问题是我似乎无法弄清楚如何绘制外键和地图的键将构造表的组合键这一事实......这是由于缺乏使用Hibernate的经验。这是我最初的尝试,让这个工作:




 <复合-ID> 
< meta attribute =use-in-equals> true< / meta>
< / key-many-to-one>
< / composite-id>

< map lazy =falsename =datatable =setup>
< key column =user_idproperty-ref =user/>
< composite-map-key class =Command.Setup>
< key-property name =datacolumn =setup_itemtype =string/>
< / composite-map-key>

< element column =setup_valuenot-null =truetype =string/>
< / map>






任何见解如何正确地映射这种常见的场景将是最受赞赏的!

解决方案

如您所示,您的不一致映射

你说Setup类定义了一个复合主键(注意我创建了一个复合主键类(SetupId - 见下图),它必须实现Serializable和equals和hashcode方法)

  package ar.domain; 

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

public class Setup实现Serializable {

私有SetupId setupId;

私人用户用户;
private Map data = new HashMap();

public SetupId getSetupId(){
return setupId;
}

public void setSetupId(SetupId setupId){
this.setupId = setupId;
}

public User getUser(){
return user;
}

public void setUser(User user){
this.user = user;
}

public Map getData(){
return data;
}

public void setData(Map data){
this.data = data;
}


public static class SetupId implements Serializable {
$ b $ private Integer userId;
private String setupItem;

public String getSetupItem(){
return setupItem;
}

public void setSetupItem(String setupItem){
this.setupItem = setupItem;
}

public Integer getUserId(){
return userId;
}

public void setUserId(Integer userId){
this.userId = userId;
}

@Override
public boolean equals(Object o){
if(o == null)
return false;

if(!(o instanceof SetupId))
return false;

final SetupId other =(SetupId)o;
if(!(getUserId()。equals(other.getUserId())))
return false;
if(!(getSetupItem()。equals(other.getSetupItem())))
return false;

返回true;
}

@Override
public int hashCode(){
int hash = 7;
hash = 11 * hash +(getUserId()!= null?getUserId()。hashCode():0);
hash = 11 * hash +(getSetupItem()!= null?getSetupItem()。hashCode():0);
返回散列;
}

}

}

因为你的Setup类有一个Map类型的Map,你应该在定义它的关系时定义它的复合外键(见关键元素)

 < class name =ar.domain.Setup> 
< composite-id name =setupIdclass =ar.domain.Setup $ SetupId>
< key-property name =userIdtype =integercolumn =USER_ID/>
< / composite-id>
< key>
< column name =SETUP_ITEM/>
< column name =USER_ID/>
< / key>
< map-key column =USER_ID/>
< element column =SETUP_VALUEnot-null =truetype =string/>
< / map>
< / class>

同时,使用复合外键列作为map-key(USER_ID,右?)这是没有意义的。为什么?


  • Hibernate 不允许更新(复合)主键列


除此之外,Hibernate 不支持自动生成的复合主键



假设这里是你的SETUP表

  SETUP_ITEM USER_ID 
0 1
0 2

而你的DATA_TABLE

  SETUP_ITEM USER_ID 
0 1

无论您尝试以下操作,会发生什么

  Integer userId = 3; 
String setupValue =someValue;

setup.getData()。put(userId,setupValue);

由于SETUP表没有定义USER_ID,其值为3,所以您会看到违反约束



请记住


有一个(复合)主键,它不能更新,避免用它来改变依赖它的可变属性。否则,Hibernate会投诉它。



I'm trying to setup a simple EAV pattern in my web app using Java/Spring MVC and Hibernate. I can't seem to figure out the magic behind the hibernate XML setup for this scenario.

My database table "SETUP" has three columns:

  • user_id (FK)
  • setup_item
  • setup_value

The database composite key is made up of user_id | setup_item

Here's the Setup.java class:

public class Setup implements CommonFormElements, Serializable {
  private Map data = new HashMap();
  private String saveAction;
  private Integer speciesNamingList;
  private User user;

  Logger log = LoggerFactory.getLogger(Setup.class);

  public String getSaveAction() {
    return saveAction;
  }

  public void setSaveAction(String action) {
    this.saveAction = action;
  }

  public User getUser() {
    return user;
  }

  public void setUser(User user) {
    this.user = user;
  }

  public Integer getSpeciesNamingList() {
    return speciesNamingList;
  }

  public void setSpeciesNamingList(Integer speciesNamingList) {
    this.speciesNamingList = speciesNamingList;
  }

  public Map getData() {
    return data;
  }

  public void setData(Map data) {
    this.data = data;
  }
}

My problem with the Hibernate setup, is that I can't seem to figure out how to map out the fact that a foreign key and the key of a map will construct the composite key of the table... this is due to a lack of experience using Hibernate. Here's my initial attempt at getting this to work:

<composite-id>
  <key-many-to-one foreign-key="id" name="user" column="user_id" class="Business.User">
    <meta attribute="use-in-equals">true</meta>
  </key-many-to-one>
</composite-id>

<map lazy="false" name="data" table="setup">
  <key column="user_id" property-ref="user"/>
  <composite-map-key class="Command.Setup">
    <key-property name="data" column="setup_item" type="string"/>
  </composite-map-key>

  <element column="setup_value" not-null="true" type="string"/>
</map>

Any insight into how to properly map this common scenario would be most appreciated!

解决方案

As shown by yourself, you have a inconsistent mapping

You said Setup class defines a composite primary key (Notice i have created a composite primary key class (SetupId - see bellow) which must implements Serializable and equals and hashcode method)

package ar.domain;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

public class Setup implements Serializable {

    private SetupId setupId;

    private User user;
    private Map data= new HashMap();

    public SetupId getSetupId() {
        return setupId;
    }

    public void setSetupId(SetupId setupId) {
        this.setupId = setupId;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Map getData() {
        return data;
    }

    public void setData(Map data) {
        this.data = data;
    }


    public static class SetupId implements Serializable {

        private Integer userId;
        private String setupItem;

        public String getSetupItem() {
            return setupItem;
        }

        public void setSetupItem(String setupItem) {
            this.setupItem = setupItem;
        }

        public Integer getUserId() {
            return userId;
        }

        public void setUserId(Integer userId) {
            this.userId = userId;
        }

        @Override
        public boolean equals(Object o) {
            if (o == null)
                return false;

            if (!(o instanceof SetupId))
                return false;

            final SetupId other = (SetupId) o;
            if (!(getUserId().equals(other.getUserId())))
                return false;
            if (!(getSetupItem().equals(other.getSetupItem())))
                return false;

            return true;
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 11 * hash + (getUserId() != null ? getUserId().hashCode() : 0);
            hash = 11 * hash + (getSetupItem() != null ? getSetupItem().hashCode() : 0);
            return hash;
        }

    }

}

Because of your Setup class has a Map of value Type, you should define its composite foreign key when defining its relationship (see key element)

<class name="ar.domain.Setup">
    <composite-id name="setupId" class="ar.domain.Setup$SetupId">
        <key-property name="setupItem" type="string" column="SETUP_ITEM"/>
        <key-property name="userId" type="integer" column="USER_ID"/>
    </composite-id>
    <many-to-one name="user" class="ar.domain.User" column="USER_ID" insert="false" update="false"/>
    <map name="data" table="DATA_TABLE">
        <key>
            <column name="SETUP_ITEM"/>
            <column name="USER_ID"/>
        </key>
        <map-key column="USER_ID"/>
        <element column="SETUP_VALUE" not-null="true" type="string"/>
    </map>
</class>

And, at the same time, use a composite foreign key column as map-key (USER_ID, right ?) which does not make sense. Why ?

  • Hibernate does not allow you update a (composite) primary key column

Besides that, Hibernate does not support automatic generation of composite primary key

Suppose here goes your SETUP Table

SETUP_ITEM USER_ID
0          1
0          2

And your DATA_TABLE

SETUP_ITEM USER_ID
0          1

What happens whether you try the following one

Integer userId = 3;
String setupValue = "someValue";

setup.getData().put(userId, setupValue);

Because of SETUP Table does not define a USER_ID which value is 3, you will see a constraint violation.

Keep it in mind

When you have a (composite) primary key, which can not be updatable, avoid to use it, someway, to change a mutable property which depends on it. Otherwise, Hibernate will complain it.

这篇关于用户使用Hibernate实现EAV模式 - &gt;设置关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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