今天要写的内容其实不多,本打算将hibernate对集合的操作的内容直接归结为一篇的,但想一想,还是分开写的比较好,毕竟前面的已经发布出去来了,废话不多说,开始吧!
依旧新建一个StudentList.java实体类,其他的属性不变,只是将hobby属性由Set集合类型变为List集合类型,还是把代码贴出来吧,希望不要嫌烦
package com.joe.entity; import java.util.List; public class StudentList { private int id; private String name; private int age; private List<String> hobby; /** * 无参构造函数 */ public StudentList(){ } public int getId() { return id; } public void setId(int 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 List<String> getHobby() { return hobby; } public void setHobby(List<String> hobby) { this.hobby = hobby; } }
接下来,大家都知道的,就是配置StudentList.hbm.xml对象关系映射文件了,先说说<list>标签吧,<list>元素用来映射java.util.List类型的属性,常用的属性和子元素有:
- name属性
- table属性
- <key>子元素
- <list-index>子元素
- <element>子元素
照样贴上代码:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > <hibernate-mapping> <!-- 一个class标签对应一个实体类,name属性指定实体类名称,table属性指定关联的数据库表 --> <class name="com.joe.entity.StudentList" table="stu_list_tab"> <!-- 主键 --> <id name="id" column="stu_id"> <!-- 提供ID自增的策略 native会根据数据库自行判断 --> <generator class="native"></generator> </id> <!-- 其他属性,name对应实体类的属性,column对应关系型数据库表的列 --> <property name="name" column="stu_name"></property> <property name="age" column="stu_age"></property> <list name="hobby" table="hobby_list_tab"> <key column="student_id"></key> <list-index column="position"></list-index> <element type="string" column="hobby"></element> </list> </class> </hibernate-mapping>
来解读一下list标签吧,<key>子元素和<element>子元素就不多讲了,主要是<list-index>子元素,我查了一下资料,也可以使用<index>,因List集合是个有序可重复的集合,所以要使用<index-index column="position"/></list-index>(或者使用<index column="position"></index>) 来标明其顺序。(position为hobby_list_tab表中附加字段),因此在插入更新时便需要维护position字段,否则索引设置错误,取出的数据就会出现空值情况。
如果<list>标签配置了inverse="true"属性, 则list的index则不会主动赋值,index列会产生空值,如果index列数据库设置可以为空,则可以正常保存数据. 而用hibernate再去查询对象数据时,会抛出null index column for collection: 此类错误.也就是说配置inverse为true的list,需要手动维护index列.感觉还是挺复杂的,有点儿搅。
当然,还可以使用<bag>(结合了List与Set)标签来配置list集合属性,可以重复且没有顺序的一种集合,是Hibernate提供的。HIbernate使用jdk的List模拟Bag。其配置与Hibernate映射list时基本相同。这里就不再讨论来,毕竟这是是冲着list来的。
依旧建立一个StudentListTest.java测试类,先写一个创建表结构的方法:
@Test public void createTable() { Configuration cfg = new Configuration().configure(); SchemaExport se = new SchemaExport(cfg); se.create(true, true); }
执行该方法,看看hibernate的执行结果:
在创建hobby_list_tab表的时候,可以看到position字段配置来not null 属性,这也体现来前面的list标签的配置,更多的信息可以在其官方文档了解,这里提供一个快捷通道:点击这里
add()方法的测试:
/** * 添加的方法 */ @Test public void add(){ Transaction tx=null; Session session=null; try{ session=HibernateUtils.getSession(); tx=session.beginTransaction(); StudentList student=new StudentList(); student.setName("zhangsan"); student.setAge(20); List<String> list=new ArrayList<String>(); list.add("basketball"); list.add("swimming"); student.setHobby(list); session.save(student); tx.commit(); }catch(HibernateException he){ if(tx!=null){ tx.rollback(); } he.printStackTrace(); }finally{ HibernateUtils.closeSession(session); } }
执行该方法,看看控制台的输出信息:
只有一点需要说明的,就是我在程序中并没有为position肤质,那position字段中是否有值,如果有,为何值?打开mysql数据库,一看便知:
哎,有值,这是hibernate提供的一种机制,它自动维护,只要你配置正确。还有一个问题需要注意,就是为什么是从0开始的而不是其他的值开始的呢?这就和我们的List集合相关联,List的底层是一个动态的数组,所以添加元素时,下标是从0开始的。
findAll()方法的测试:
@Test public void findAll(){ Transaction tx=null; Session session=null; try{ session=HibernateUtils.getSession(); tx=session.beginTransaction(); StudentList stu=(StudentList)session.get(StudentList.class, 1); System.out.println(stu.getId()+stu.getName()+stu.getAge()); tx.commit(); }catch(HibernateException he){ if(tx!=null){ tx.rollback(); } he.printStackTrace(); }finally{ HibernateUtils.closeSession(session); } }
和以前测试差不多,先只访问基本属性,我想hibernate的执行动作大家都知道了,只会有一条select语句,不会去访问hobby_list_tab表的,还是贴上图吧:
接下来,添加访问hobby属性的代码:
//访问hobby属性 List<String> hobby=stu.getHobby(); for(String str:hobby){ System.out.println(str); }
相信结果大家还是知道的,依旧贴图:
其实自我感觉这篇文章和上一篇文章有点重复,但是还不至于无聊致死,毕竟知识是一步一步学来的,接下来的一两篇,节奏大概还是这样的吧,各位看官,不要嫌我啰嗦哟。