【问题标题】:Arbitrary 'columns' from HashMap in hibernate query休眠查询中来自 HashMap 的任意“列”
【发布时间】:2012-01-23 14:13:53
【问题描述】:

假设我有一个实体用户

public class User {
    private String username;
    private String password;

    private Map<String, Object> settings = new HashMap<String, Object>();

    //Getters & setters
}

有什么方法可以在查询中使用设置映射的键? 例如:

Criterion crit = mySession.createCriterion(User.class);
crit.add(Restrictions.eq("settings.blah", 1234L));
List<User> results = crit.list();

或者通过 EL 访问地图值? 例如:

<h:dataTable value="#{myBean.users}" var="user">
    <h:column>
        <h:outputText value="#{user.blah}"/>
    </h:column>
</h:dataTable>

我可以通过简单的@OneToMany 映射部分地做到这一点,但这需要我的查询同时使用键和值,并且无法通过 EL 访问属性。

这样的事情可能吗?我如何将其与注释映射?

谢谢

编辑: 本质上,我追求的是一个“垂直表”实现,这样我就可以拥有任意字段,并且仍然能够将实体用作映射类。我不知道这是否可以通过休眠实现。

【问题讨论】:

    标签: java hibernate jsf el


    【解决方案1】:

    我从不使用 Object 作为映射的值,您可以将 String 与此映射一起使用:

    @Entity
    public class User {
    
    private int _id;
    private Map<String, String> _settings;
    
    public User() {
    
    }
    
    @Id
    @GeneratedValue
    public int getId() {
        return _id;
    }
    
    public void setId(int id) {
        _id = id;
    }
    
    @ElementCollection
    @MapKeyColumn(name = "SETTINGS_KEY")
    @CollectionTable(name = "USER_SETTINGS", joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "SETTING")
    public Map<String, String> getSettings() {
        return _settings;
    }
    
    public void setSettings(Map<String, String> settings) {
        _settings = settings;
    }
    
    }
    

    如果您需要使用不同类型的列,则必须使用接口作为映射的值,如下所示:

    @Entity
    public class TestSettings {
    
        private int _id;
        private Map<String, SettingValue<?>> _settings;
    
        public TestSettings() {
    
        }
    
        @Id
        @GeneratedValue
        public int getId() {
            return _id;
        }
    
        public void setId(int id) {
            _id = id;
        }
    
        @OneToMany
        @MapKeyColumn(name = "SETTINGS_KEY")
        @CollectionTable(name = "USER_SETTINGS", joinColumns = @JoinColumn(name = "user_id"))
        @Column(name = "SETTING")
        public Map<String, SettingValue<?>> getSettings() {
            return _settings;
        }
    
        public void setSettings(Map<String, SettingValue<?>> settings) {
            _settings = settings;
        }
    
    }
    

    SettingValue 抽象类:

    @Entity
    @Inheritance(strategy=InheritanceType.JOINED)
    public abstract class SettingValue<V> implements Serializable {
    
        private static final long serialVersionUID = 3355627640146408150L;
    
        private Integer _id;
    
        public SettingValue() {
            super();
        }
    
        @Id @GeneratedValue
        public Integer getId() {
            return _id;
        }
    
        public void setId(Integer id) {
            _id = id;
        }
    
        @Transient
        public abstract V getValue();
    
        public abstract void setValue(V value);
    
    }
    

    settingValue 字符串实现:

    @Entity
    @PrimaryKeyJoinColumn(name="settingvalue_id", referencedColumnName="id")
    public class TextSettingValue extends SettingValue<String> implements Serializable {
    
        private String _value;
    
        public TextSettingValue() {
            super();
        }
    
        @Override
        public void setValue(String value) {
            _value = value;
        }
    
        @Override
        public String getValue() {
            return _value;
        }
    
    }
    

    您必须为要支持的每种类型创建一个 SettingValue 实现,这样您就可以为每种类型获得一个表,其中有一列来保存您的值。

    【讨论】:

      猜你喜欢
      • 2015-12-07
      • 2011-08-09
      • 2012-12-23
      • 2011-04-23
      • 1970-01-01
      相关资源
      最近更新 更多