zoukankan      html  css  js  c++  java
  • hibernate学习系列-----(6)hibernate对集合属性的操作之Set集合篇

    先说一段废话吧,本打算每天把所学的知识总结为博客的,但是昨天为什么没有写呢?没有学习吗?No,那是为什么?贪玩,对,这位同学说对了,老实说昨天感觉身体不怎么舒服,大家都知道,这其实就是为自己懒找借口,好吧,废话先唠到这儿,下面进入正题。


    先说说概念吧

    在持久化类中,有时会使用到值类型的对象属性,所谓值类型的对象,是指它对应的类没有对象标识符属性,也就是我们在前面所说的OID,只能作为一个持久化类的属性使用。如果持久化类中一个值类型的集合,那么就需要一张额外的数据库表来保存这个值类型集合的数据,这张表被称为集合表。

    需要注意的一点是,hibernate3.0以后开始支持大部分重要的JDK集合接口映射,当然,现在的开发基本上都是使用3.0以后的版本吧,

    为此,我们在项目中新建一个实体类吧,我取名StudentSet.java,给它简单地赋予几个属性,其中比较特别的属性就是hoppy属性,它是一个Set集合类型的,表现为一多关系:

    package com.joe.entity;
    
    import java.util.Set;
    
    /**
     * 
     * @author Joe
     * StudentSet java bean
     */
    public class StudentSet {
        
        private int id;
        private String name;
        private int age;
        private Set<String> hobby;
        
        /**
         * 无参的构造函数
         */
        public StudentSet(){
            
        }
        
        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 Set<String> getHobby() {
            return hobby;
        }
        public void setHobby(Set<String> hobby) {
            this.hobby = hobby;
        }
    
    }

    在配置实体关心映射文件的时候,要特别注意对于set标签的配置:<set>元素用来映射java.util.Set类型的属性,常用的属性和子元素有:

    1. name属性:对应实体类中Set集合属性
    2. table属性:当前Set集合所对应的表结构
    3. <key>子元素:Set集合对应的表结构的外键列
    4. <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.StudentSet" table="stu_set_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>
            
            <set name="hobby" table="hobby_tab">
                <key column="student_id"></key>
                <element type="string" column="hobby"></element>
            </set>
            
        </class>
    </hibernate-mapping>

    其中key是hobby_tab的外键,element元素标签是映射到数据库中的集合的字段,另外,一定要为element标签设置type属性,否则是会抛异常的。编写好了过后,不要忘了在hibernate.cfg.xml文件中添加映射,接下来,在test文件夹下的测试包中新建一个StudentSetTest.java测试类,在该类下,先添加下面的方法:

    @Test
        public void createTable() {
            Configuration cfg = new Configuration().configure();
            SchemaExport se = new SchemaExport(cfg);
            se.create(true, true);
        }

    这个方法就不介绍了,执行该方法,看看hibernate都做了些什么?

    QQ截图20150808105728

    可以发现,除了创建stu_set_tab表以外,还创建了一张名为hobby_tab的表,并且把student_id设置为hobby_tab的外键。

    测试添加

    紧跟上面的步伐,添加一个add()方法:

    /**
         * 添加的方法
         */
        @Test
        public void add(){
            Transaction tx=null;
            Session session=null;
            try{
                session=HibernateUtils.getSession();
                tx=session.beginTransaction();
                StudentSet student=new StudentSet();
                student.setName("zhangsan");
                student.setAge(20);
                
                @SuppressWarnings({ "rawtypes", "unchecked" })
                Set<String> set=new HashSet();
                set.add("basketball");
                set.add("swimming");
                
                student.setHobby(set);
                
                session.save(student);
                
                
                tx.commit();
            }catch(HibernateException he){
                if(tx!=null){
                    tx.rollback();
                }
                he.printStackTrace();
            }finally{
                HibernateUtils.closeSession(session);
            }
        }

    调用session的save()方法,测试该方法,在看看hibernate又为我们做了什么?

    QQ截图20150808110600

    有点可惜,屏幕不够大,看不完整,但思路是完整的,这几句sql还是好理解的,就是简单的插入操作,不再多言。

    get()方法

    这个测试更有趣一点:

    /**
         * 查询方法
         */
        @Test
        public void findAll(){
            Transaction tx=null;
            Session session=null;
            try{
                session=HibernateUtils.getSession();
                tx=session.beginTransaction();
                
                StudentSet stu=(StudentSet)session.get(StudentSet.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);
            }
        }

    在次测试,看看控制台的输出信息:

    QQ截图20150808111231

    咦,为什么没有查询hobby_tab表呢?从上面的程序代码中,我们并没有访问hobby属性,改进程序代码,添加访问hobby属性的代码:

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

    再次测试,结果应该都能猜到的,

    QQ截图20150808111739

    如我们所料,hibernate执行了两条sql语句。先根据id查询学习的基本信息,再根据id在hobby_tab中查询对应的数据。前面不是说过了吗?只有访问对象的非对象表示符(OID)属性的时候,才会发起select语句,体现了hibernate的延迟加载、懒加载的特性。

    好吧,把昨天的博客补上了,稍稍有点简陋,当然还有很多没有总结到的,也还有很多需要修正的,希望园子里的大神们可以给我提些意见和建议。

  • 相关阅读:
    20140327工作室日志
    20140326学习工作室日志
    标准连接池实现
    JDBC
    监听器
    数据表多对多
    MATLAB 中几个颜色空间的坐标范围
    RabbitMQ(一)
    Web Service之Axis(二)
    Web Service之CXF(四)
  • 原文地址:https://www.cnblogs.com/doctorJoe/p/4712829.html
Copyright © 2011-2022 走看看