1、实体类,代码如下:
package learn.hibernate.bean; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * 持久化类设计 * 注意: * 持久化类通常建议要有一个持久化标识符(ID) * 持久化标识符通常建议使用封装类(例如:Integer 因为基本类型存在默认值) * 持久化类通常建议手动添加一个无参构造函数 (因为有些操作是通过放射机制进行的) * 属性通常建议提供 getter/setter 方法 * 持久化类不能使用 final 修饰 * 持久化类中如果使用了集合类型数据,只能使用集合所对应的接口类型来声明(List/Map/Set) * 如下:ArrayList list = new ArrayList(); 不行 * List list = new ArrayList(); 可行 */ public class Person { private Integer id; private String name; private int age; private int passwork; private Date birthday; /** * 数组 同构类型数据 (效率低) * 通过 下标 访问数组中的元素 */ private String[] myArr; /** * List * 通过 下标 访问数组中的元素 */ private List myList; /** * 通过 key 访问value */ private Map myMap; /** * 只有值本身 */ private Set mySet; public Person() { } public Person(String name, int age, int passwork, Date birthday) { super(); this.name = name; this.age = age; this.passwork = passwork; this.birthday = birthday; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", age=" + age + ", passwork=" + passwork + ", birthday=" + birthday + "]"; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getPasswork() { return passwork; } public void setPasswork(int passwork) { this.passwork = passwork; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String[] getMyArr() { return myArr; } public void setMyArr(String[] myArr) { this.myArr = myArr; } public List getMyList() { return myList; } public void setMyList(List myList) { this.myList = myList; } public Map getMyMap() { return myMap; } public void setMyMap(Map myMap) { this.myMap = myMap; } public Set getMySet() { return mySet; } public void setMySet(Set mySet) { this.mySet = mySet; } }
2、映射文件,代码如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="learn.hibernate.bean"> <class name="Person" table="t_person"> <id name="id" column="person_id"> <generator class="native"/> </id> <property name="name" column="t_name"/> <property name="age"/> <property name="passwork"/> <property name="birthday"/> <!-- 数组的映射配置 table 可选--> <array name="myArr" table="t_array"> <!-- t_array 表保存数组中的数据,需要和 t_person 表建立关联关系(一对多),所有需要一个 key list-index 指定数组下标存储列的映射 element 表示数组中的元素存储列的映射 --> <key column="id"/> <list-index column="arr_indexs"/> <element column="arr_values"/> </array> <!-- list 的映射配置 list 和 array 一样--> <list name="myList"> <key column="id"/> <list-index column="list_indexs"/> <element column="list_values"/> </list> <!-- map 的映射配置 --> <map name="myMap"> <!-- map-key 指定 map 集合的 key 数据存储的列映射,并指定类型 element 表示 map 中的元素存储列的映射 --> <key column="id"/> <map-key column="map_keys" type="string"/> <element column="map_values"/> </map> <!-- set 的映射配置 set没有下标和 key,只需要元素即可 --> <set name="mySet"> <key column="id"/> <element column="set_values"/> </set> </class> </hibernate-mapping>
3、测试代码:
package learn.hibernate.test; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import learn.hibernate.bean.Person; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestHibernate { SessionFactory factory = null; Session session = null; Transaction tx = null; /** * 测试之前初始化数据 * @throws Exception */ @SuppressWarnings("deprecation") @Before public void setUp() throws Exception { System.out.println("---------初始化数据----------"); Configuration config = new Configuration().configure(); ServiceRegistry sr = new ServiceRegistryBuilder() .applySettings(config.getProperties()).buildServiceRegistry(); factory = config.buildSessionFactory(sr); session = factory.openSession(); } /** * 测试之后释放(销毁)数据 * @throws Exception */ @After public void tearDown() throws Exception { System.out.println("---------释放数据----------"); if(session.isOpen()){ session.close(); } } @Test public void testAdd(){ Person p = new Person("June",22,123456,new Date()); String[] myArr = {"A","B","C","D"}; List myList = new ArrayList(); myList.add("北京"); myList.add("上海"); myList.add("长沙"); myList.add("深圳"); Map myMap = new HashMap(); myMap.put(1, "中国"); myMap.put(2, "湖南"); myMap.put(3, "郴州"); myMap.put(4, "桂阳"); Set mySet = new HashSet(); mySet.add("跑步"); mySet.add("游泳"); mySet.add("篮球"); p.setMyArr(myArr); p.setMyList(myList); p.setMyMap(myMap); p.setMySet(mySet); tx = session.beginTransaction(); session.persist(p); tx.commit(); } }
4、测试,会发现报错:
org.hibernate.MappingException: No type name at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:319) at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:310) at org.hibernate.mapping.Collection.validate(Collection.java:315) at org.hibernate.mapping.IndexedCollection.validate(IndexedCollection.java:89) at org.hibernate.cfg.Configuration.validate(Configuration.java:1362) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1849) at learn.hibernate.test.TestHibernate.setUp(TestHibernate.java:44) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) java.lang.NullPointerException at learn.hibernate.test.TestHibernate.tearDown(TestHibernate.java:55) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
原因是没有给映射文件中的字段指定数据类型
修改映射文件,代码如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="learn.hibernate.bean"> <class name="Person" table="t_person"> <id name="id" column="person_id"> <generator class="native"/> </id> <property name="name" column="t_name"/> <property name="age"/> <property name="passwork"/> <property name="birthday"/> <!-- 数组的映射配置 table 可选--> <array name="myArr" table="t_array"> <!-- t_array 表保存数组中的数据,需要和 t_person 表建立关联关系(一对多),所有需要一个 key list-index 指定数组下标存储列的映射 element 表示数组中的元素存储列的映射 --> <key column="id"/> <list-index column="arr_indexs"/> <element type="java.lang.String" column="arr_values"/> </array> <!-- list 的映射配置 list 和 array 一样--> <list name="myList"> <key column="id"/> <list-index column="list_indexs"/> <element type="java.lang.String" column="list_values"/> </list> <!-- map 的映射配置 --> <map name="myMap"> <!-- map-key 指定 map 集合的 key 数据存储的列映射,并指定类型 element 表示 map 中的元素存储列的映射 --> <key column="id"/> <map-key type="java.lang.String" column="map_keys"/> <element type="java.lang.String" column="map_values"/> </map> <!-- set 的映射配置 set没有下标和 key,只需要元素即可 --> <set name="mySet"> <key column="id"/> <element type="java.lang.String" column="set_values"/> </set> <!-- bag 可以重复存放数据,但是修改和删除的时候没有 id 值,所以不知道具体是哪一条,所以会将全部数据删除,重新插入新数据 --> <!-- <bag name="items" table="t_item"> <key column="id"/> <element type="java.lang.String" column="name"/> </bag> --> <!-- bag 的一个升级 数据带ID --> <!-- <idbag name="items" table="t_item"> <collection-id type="java.lang.String" column="cid"> <generator class="uuid.hex"/> </collection-id> <key column="id"/> <element type="java.lang.String" column="name"/> </idbag> --> </class> </hibernate-mapping>
所有的有序集合类(maps,lists,arrays)都拥有一个由 <key> 和 <index> 组成的主键。这种情况下集合类的更新是非常高效的 — 主键已经被有效的索引,因此当 Hibernate 试图更新或删除一行时,可以迅速找到该行数据。
集合(sets)的主键由 <key> 和其他元素字段构成。对于有些元素类型来说,这很低效,特别是组合元素或者大文本、大二进制字段;数据库可能无法有效的对复杂的主键进行索引。另一方面,对于一对多、多对多关联,特别是合成的标识符来说,集合也可以达到同样的高效性能。( 附注:如果你希望 SchemaExport 为你的 <set> 创建主键,你必须把所有的字段都声明为 not-null="true"。)
<idbag> 映射定义了代理键,因此它总是可以很高效的被更新。事实上,<idbag> 拥有着最好的性能表现。
Bag 是最差的。因为 bag 允许重复的元素值,也没有索引字段,因此不可能定义主键。 Hibernate 无法判断出重复的行。当这种集合被更改时,Hibernate 将会先完整地移除 (通过一个(in a single DELETE))整个集合,然后再重新创建整个集合。因此 Bag 是非常低效的。
请注意:对于一对多关联来说,“主键”很可能并不是数据库表的物理主键。但就算在此情况下,上面的分类仍然是有用的。(它仍然反映了 Hibernate 在集合的各数据行中是如何进行“定位”的。)
文字部分来自:
http://ears.iteye.com/blog/1508557
也可以查看:
http://www.cnblogs.com/otomedaybreak/archive/2012/01/18/2325993.html