来自HashMap的任意“列”在hibernate查询中

时间:2012-01-23 14:13:54

标签: java hibernate jsf el

假设我有一个实体用户

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访问属性。

这样的事情可能吗?我如何用注释来映射它?

由于

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

1 个答案:

答案 0 :(得分: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 String implementation:

@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实现,这样您就可以获得每个类型的表格,并使用一列来保存您的值。