我面临着复杂的要求,让我很困惑。帮助...
休眠:4.3.6 MySql 5.6.21
支持标准产品的动态扩展,例如: 标准POJO:
package com.inspur.gsp;
import java.util.HashMap;
import java.util.Map;
public class Person {
private String id;
private String age;
private Map<CustomPK, Person_T> i18nProperty = new HashMap<CustomPK, Person_T>();
private Map<String, HashMap<String, Object>> extProperty = new HashMap<String, HashMap<String, Object>>();
public Map<CustomPK, Person_T> getI18nProperty() {
return i18nProperty;
}
public void setI18nProperity(Map<CustomPK, Person_T> i18nProperty) {
this.i18nProperty = i18nProperty;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Map<String, HashMap<String, Object>> getExtProperty() {
return extProperty;
}
public void setExtProperty(Map<String, HashMap<String, Object>> extProperty) {
this.extProperty = extProperty;
}
}
因此,ExtProperity的类型为Map<String, Map<String, Object>>
,它将用于存储扩展属性。然后我们需要将它持久化到数据库。
这是我的hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Nov 3, 2014 11:48:31 AM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.inspur.gsp.Person" table="GSPPerson">
<id name="id" type="java.lang.String">
<column name="ID" length="36" />
<generator class="assigned" />
</id>
<property name="age" type="java.lang.String">
<column name="age" length="128" />
</property>
<map name="i18nProperty" table="GSPPerson_T">
<key column="ID"></key>
<composite-map-key class="com.inspur.gsp.CustomPK">
<key-property name="culture"></key-property>
</composite-map-key>
<composite-element class="com.inspur.gsp.Person_T">
<property name="description" column="description"></property>
<property name="comments" column="comments"></property>
</composite-element>
</map>
<map name="extProperty" table="GSPPerson_Ext">
<key column="ID"></key>
<map-key type="string" column="ID" />
<composite-element class="java.util.HashMap">
<property name="ext1" column="ext1"></property>
<property name="ext2" column="ext2"></property>
</composite-element>
</map>
</class>
</hibernate-mapping>
测试代码:
SessionFactory sf = createSessionFactory();
Person person = new Person();
person.setId("1");
person.setAge("30");
HashMap<CustomPK, Person_T> i18nProperity = new HashMap<CustomPK, Person_T>();
Person_T t1 = new Person_T();
t1.setComments("abc");
t1.setDescription("description");
Person_T t2 = new Person_T();
t2.setComments("efg");
t2.setDescription("ooooooo");
i18nProperity.put(new CustomPK("1", "cn"), t1);
i18nProperity.put(new CustomPK("1", "en"), t2);
person.setI18nProperity(i18nProperity);
HashMap<String, HashMap<String,Object>> extProperty = new HashMap<String, HashMap<String,Object>>();
HashMap<String,Object> e1 = new HashMap<String,Object>();
e1.put("ext1", 1);
e1.put("ext2", "c001");
extProperty.put("1", e1);//1 is person's id ,e1 is extension property.
person.setExtProperty(extProperty);
Session session = sf.getCurrentSession();
Transaction ts = session.beginTransaction();
session.save(person);
Person person2 = (Person) session.get(Person.class, "1");
ts.commit();
hbm.xml中的配置无法正常工作。请帮我。感谢。
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
Exception in thread "main" org.hibernate.PropertyNotFoundException: field [ext1] not found on java.util.HashMap
at org.hibernate.property.DirectPropertyAccessor.getField(DirectPropertyAccessor.java:166)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectPropertyAccessor.java:173)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectPropertyAccessor.java:158)
at org.hibernate.property.DirectPropertyAccessor.getGetter(DirectPropertyAccessor.java:181)
at org.hibernate.internal.util.ReflectHelper.getter(ReflectHelper.java:254)
at org.hibernate.internal.util.ReflectHelper.reflectedPropertyClass(ReflectHelper.java:230)
at org.hibernate.mapping.SimpleValue.setTypeUsingReflection(SimpleValue.java:362)
at org.hibernate.cfg.HbmBinder.createProperty(HbmBinder.java:2350)
at org.hibernate.cfg.HbmBinder.bindComponent(HbmBinder.java:2037)
at org.hibernate.cfg.HbmBinder.bindComposite(HbmBinder.java:1836)
at org.hibernate.cfg.HbmBinder.bindCollectionSecondPass(HbmBinder.java:2634)
at org.hibernate.cfg.HbmBinder.bindMapSecondPass(HbmBinder.java:2468)
at org.hibernate.cfg.HbmBinder$MapSecondPass.secondPass(HbmBinder.java:2843)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1695)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
at I18nTest.createSessionFactory(I18nTest.java:84)
at I18nTest.main(I18nTest.java:37)
GSPPerson的表结构是:
ID Age
1 30
GSPPerson_ext的表结构是:
ID ext1 ext2
1 1 c001
HashMap<String, HashMap<String,Object>> extProperty = new HashMap<String, HashMap<String,Object>>();
HashMap<String,Object> e1 = new HashMap<String,Object>();
e1.put("ext1", 1);
e1.put("ext2", "c001");
extProperty.put("1", e1);//1 is person's,e1 is extension property.
person.setExtProperty(extProperty);
Ext1和Ext2是扩展列,因此我们定义了Hashmap<String,HashMap<String,Object>
来存储扩展列。我们希望将Hashmap保留为扩展列。
答案 0 :(得分:0)
您在ext1
上定义了一个属性HashMap
,它没有,所以Hibernate会查找这些属性。 ext1
到底意味着什么?
此外,您将Object
放入地图中,Hibernate将无法映射该地图。
我不确定您的案例中的扩展名或嵌套地图的键代表什么,但我可能会将扩展名作为单独的实体进行建模。这样的事情:
class Extension {
String key;
Type type; //Type could be an Enum, String, a Number etc. whatever fits your needs
String value; //use a text representation of the values and convert according to the type
}
在你的Person
课程中:
Map<String, Extension> extensions = ...;
正如您所看到的,我将扩展值映射到String
而不是Object
,以便让Hibernate正确映射该值。大多数类型(至少是基元)无论如何都可以转换为字符串和从字符串转换,这样就不会有问题。如果值变得更复杂,您需要适当的字符串映射(例如JSON或XML),将值序列化为字节数组或将值设置为自定义实体。