hibernate学习系列-----(7)hibernate对集合属性的操作之List集合篇

今天要写的内容其实不多,本打算将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类型的属性,常用的属性和子元素有:

  1. name属性
  2. table属性
  3. <key>子元素
  4. <list-index>子元素
  5. <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的执行结果:

hibernate学习系列-----(7)hibernate对集合属性的操作之List集合篇

在创建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);
        }
    }

执行该方法,看看控制台的输出信息:

hibernate学习系列-----(7)hibernate对集合属性的操作之List集合篇

只有一点需要说明的,就是我在程序中并没有为position肤质,那position字段中是否有值,如果有,为何值?打开mysql数据库,一看便知:

hibernate学习系列-----(7)hibernate对集合属性的操作之List集合篇

哎,有值,这是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表的,还是贴上图吧:

hibernate学习系列-----(7)hibernate对集合属性的操作之List集合篇

接下来,添加访问hobby属性的代码:

//访问hobby属性
            List<String> hobby=stu.getHobby();
            for(String str:hobby){
                System.out.println(str);
            }

相信结果大家还是知道的,依旧贴图:

hibernate学习系列-----(7)hibernate对集合属性的操作之List集合篇

其实自我感觉这篇文章和上一篇文章有点重复,但是还不至于无聊致死,毕竟知识是一步一步学来的,接下来的一两篇,节奏大概还是这样的吧,各位看官,不要嫌我啰嗦哟。