假设我有一个实体用户
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是否可以实现这一点。
答案 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实现,这样您就可以获得每个类型的表格,并使用一列来保存您的值。