zoukankan      html  css  js  c++  java
  • Hibernate学习(五)

    自关联测试案例

    1、创建表

    drop  table if exists  t_category ;
        
        create table t_category (
            id int(5) primary key ,
            name varchar(150) ,
            position int(2) ,
            parent_id int(5) ,
            foreign key ( parent_id ) references t_category ( id )
        );
        
        insert into t_category ( id , name , position , parent_id )  values (  1001 , '图书音像' , 2 , null ) ;
        insert into t_category ( id , name , position , parent_id )  values (  1002 , '小说' , 2  , 1001 ) ;
        insert into t_category ( id , name , position , parent_id )  values (  1003 , '教学辅导' , 1  , 1001 ) ;
        insert into t_category ( id , name , position , parent_id )  values (  1004 , '计算机' , 3  , 1001 ) ;
        
        insert into t_category ( id , name , position , parent_id )  values (  1005 , '玄幻' , 2  , 1002 ) ;
        insert into t_category ( id , name , position , parent_id )  values (  1006 , '言情' , 1  , 1002 ) ;
        insert into t_category ( id , name , position , parent_id )  values (  1007 , '武侠' , 3  , 1002 ) ;
        
        insert into t_category ( id , name , position , parent_id )  values (  2001 , '数码产品' , 1 , null ) ;
        insert into t_category ( id , name , position , parent_id )  values (  2002 , '手机' , 1 , 2001 ) ;
        insert into t_category ( id , name , position , parent_id )  values (  2003 , '电脑' , 2 , 2001 ) ;
        insert into t_category ( id , name , position , parent_id )  values (  2004 , '相机' , 3 , 2001 ) ;
        
        insert into t_category ( id , name , position , parent_id )  values (  2005 , '魅族' , 2 , 2002 ) ;
        insert into t_category ( id , name , position , parent_id )  values (  2006 , '小米' , 1 , 2002 ) ;
        insert into t_category ( id , name , position , parent_id )  values (  2007 , '坚果Pro' , 3 , 2002 ) ;

    分类中有一个外键parent_id 来指定父分类,并通过position来指定分类的位置。

    2、持久化类

    package ecut.self.entity;
    
    import java.io.Serializable;
    import java.util.List;
    
    public class Category implements Serializable {
    
        private static final long serialVersionUID = 4807135047518624567L;
        
        /** 对象标识符属性 ( 属性值就是 对象标识符 ( Object Identifier ) )*/
        private Integer id ;
        /** 分类的名称 */
        private String name ; 
        /** 将来在 界面 中显示时的位置*/
        private int position ;
        
        /** 先 把 当前的分类 对象 当作 一个 父分类来对待 ,那么它可能对应 多个 子分类 */
        private List<Category> categories ; // 维护 从 父分类( one ) 到 子分类 ( many ) 的 一对多 关联关系
        
        /** 再 把 当前分类对象 当作一个 子分类来对待,那么它可能有一个 父分类 */
        private Category parent ;  // 维护 从  子分类 ( many ) 到  父分类( one ) 的 多对一 关联关系
        
        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 getPosition() {
            return position;
        }
    
        public void setPosition(int position) {
            this.position = position;
        }
    
        public List<Category> getCategories() {
            return categories;
        }
    
        public void setCategories(List<Category> categories) {
            this.categories = categories;
        }
    
        public Category getParent() {
            return parent;
        }
    
        public void setParent(Category parent) {
            this.parent = parent;
        }
        
    }

    3、映射文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
    
        <class name="ecut.self.entity.Category" table="t_category">
        
            <id name="id" type="integer" column="id" >
                <!-- <generator class="increment" />  -->
            </id>
        
            <property name="name" type="string" column="name" />
            
            <property name="position" type="int" column="position" />
            
            <!-- 先 把 当前的分类 对象 当作 一个 父分类来对待 ,那么它可能对应 多个 子分类 -->
            <list name="categories" cascade="all">
                <key column="parent_id" />
                <!-- list是有顺序的,下标从0开始 , 添加在第一个子类的时候放在list下标为1的位置上,即position从1开始-->
                <!-- <index base="1" column="position" />  -->
                <list-index base="1" column="position" /> 
                <!-- 指定 对方  ( many 一方 )  的类型 ( List 集合中存放的元素的类型 )  -->
                <one-to-many class="ecut.self.entity.Category" />
            </list>
            
            <!-- 再 把 当前分类对象 当作一个 子分类来对待,那么它可能有一个 父分类  -->
            <!-- 维护从 子分类 ( many ) 到  父分类( one )  的 多对一 关联 -->
            <many-to-one  cascade="all" name="parent" class="ecut.self.entity.Category" column="parent_id" />
        
        </class>
        
    </hibernate-mapping>

    4、hibernate配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
        
        
    <hibernate-configuration>
    
        <session-factory>
        
            <!-- 指定连接数据库的基本信息 -->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF8</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">123456</property>
            
            <!-- 设置事务隔离级别 , 取值可以是 1、2、4、8 -->
            <property name="hibernate.connection.isolation">1</property>
            <!-- 设置事务是否自动提交 , 取值可以是 true 、false -->
            <property name="hibernate.connection.autocommit">false</property>
            
            <!-- 指定数据方言类 -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
            
            <!-- 指示是否显示 执行过的 SQL 语句 -->
            <property name="hibernate.show_sql">true</property>
            <!-- 指示是否对 SQL 语句进行格式化输出 -->
            <property name="hibernate.format_sql">false</property>
            
            <mapping resource="ecut/self/entity/Category.hbm.xml"/>
            
        </session-factory>
    
    </hibernate-configuration>

    5、测试类

    第一个角度: 从 一对多角度测试
      存:  保存一个分类,并为其添加子分类
      取:  获取一个分类,并获取其子分类

    package ecut.self.test.onetomany;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import ecut.self.entity.Category;
    
    public class TestOneToMany {
        private SessionFactory factory ;
        private Session session ; 
        
        public @Before void init() {
            // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
            Configuration config = new Configuration();
            // 读取配置文件
            config.configure("ecut/self/hibernate.cfg.xml");
    
            //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件
    
            // 使用 Configuration 创建 SessionFactory
            factory = config.buildSessionFactory();
            
            // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
            session = factory.openSession();
        }
        
        /** 获取一个分类,并获取其子分类 */
        public @Test void loadCategory(){
            
            Category c = session.find( Category.class ,  1001 );
            
            if( c == null ){
                System.out.println( "未找到分类" );
            } else {
                System.out.println( "分类: " + c.getName());
                
                 List<Category> categories = c.getCategories();
                 
                 if( categories == null || categories.isEmpty() ) {
                     System.out.println( c.getName() + " 没有子分类" );
                 } else {
                     for( int i = 0 , n =categories.size() ; i < n ; i++ ){
                         Category s = categories.get( i ); 
                         System.out.println( "	" + s.getName() + " , " + s.getPosition() );
                     }
                 }
                 
            }
            
        }
        
        /** 保存一个分类,并指定其子分类 ( 子分类被一起保存 )*/
        public @Test void saveCategory(){
            Category c =new Category();
            c.setId(3001);
            c.setName("动漫");
            List<Category> categories =  new ArrayList<Category>() ;    
            Category c1 =new Category();
            c1.setId(3002);
            c1.setName("火影忍者");
            c1.setParent(c);
            categories.add(c1);
            Category c2 =new Category();
            c2.setId(3003);
            c2.setName("海贼王");
            c2.setParent(c);
            categories.add(c2);
            Category c3 =new Category();
            c3.setId(3004);
            c3.setName("名侦探柯南");
            c3.setParent(c);
            categories.add(c3);
            c.setCategories(categories);
            Transaction t=session.getTransaction();
            t.begin();
            session.save(c);
            t.commit();
        }
        
        public @After void destory(){
            session.close();
            factory.close();
        }
    
    }

    若id和position在映射配置文件中配置了,但测试的时候在测试类中由setter了position和id,就会抛出如下异常:

    javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    第二个角度: 从 多对一角度测试    
      存:  保存一个分类,并为其添加父分类
      取:  获取一个分类,并获取其父分类

    package ecut.self.test.manytoone;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import ecut.self.entity.Category;
    
    public class TestManyToOne {
        
        private SessionFactory factory ;
        private Session session ; 
        
        public @Before void init() {
            // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
            Configuration config = new Configuration();
            // 读取配置文件
            config.configure("ecut/self/hibernate.cfg.xml");
            //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件
    
            // 使用 Configuration 创建 SessionFactory
            factory = config.buildSessionFactory();
            
            // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
            session = factory.openSession();
        }
        
        public @Test void loadCategory(){
            
            Category s = session.find( Category.class  , 1002 );
            
            if( s == null ){
                System.out.println( "未找到分类" );
            } else {
                System.out.println( s.getName() );
                
                Category p = s.getParent();
                if( p == null ){
                    System.out.println( s.getName() + "是一个顶级分类" );
                } else {
                    System.out.println( s.getName() + " 分类的 父分类是 " + p.getName() );
                }
            }
            
        }
        public @Test void saveCategory(){
            Category p =new Category();
            p.setId(4001);
            p.setName("银行");
            Category s =new Category();
            s.setId(4002);
            s.setName("中国工商银行");
            s.setParent(p);
            Transaction t=session.getTransaction();
            t.begin();
            session.save(s);
            t.commit();
        }
        public @After void destory(){
            session.close();
            factory.close();
        }
    
    }

    第三个角度: 综合
      存: 保存一个分类,指定其 父分类 和 子分类
      取: 获取一个分类,并获取其 父分类 和 子分类

    package ecut.self.test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import ecut.self.entity.Category;
    
    public class TestSelf {
        
        private SessionFactory factory ;
        private Session session ; 
        
        public @Before void init() {
            // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
            Configuration config = new Configuration();
            // 读取配置文件
            config.configure("ecut/self/hibernate.cfg.xml");
            //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件
    
            // 使用 Configuration 创建 SessionFactory
            factory = config.buildSessionFactory();
            
            // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
            session = factory.openSession();
        }
        
        public @Test void loadCategory(){
            
            Category s = session.find( Category.class  , 2002 );
            
            if( s == null ){
                System.out.println( "未找到分类" );
            } else {
                System.out.println( s.getName() );
                
                Category p = s.getParent();
                if( p == null ){
                    System.out.println( s.getName() + "是一个顶级分类" );
                } else {
                    System.out.println( s.getName() + " 分类的 父分类是 " + p.getName() );
                }
                
                List<Category> categories = s.getCategories();
                 
                 if( categories == null || categories.isEmpty() ) {
                     System.out.println( s.getName() + " 没有子分类" );
                 } else {
                     for( int i = 0 , n =categories.size() ; i < n ; i++ ){
                         Category c = categories.get( i ); 
                         System.out.println( "	" + c.getName() + " , " + c.getPosition() );
                     }
                 }
            }
            
        }
        public @Test void saveCategory(){
            Category p =new Category();
            p.setId(5001);
            p.setName("支付");
            Category s =new Category();
            s.setId(5002);
            s.setName("网银");
            s.setParent(p);
            List<Category> categories =  new ArrayList<Category>() ;    
            Category c1 =new Category();
            c1.setId(5003);
            c1.setName("B2B");
            c1.setParent(s);
            categories.add(c1);
            Category c2 =new Category();
            c2.setId(5004);
            c2.setName("B2C");
            c2.setParent(s);
            categories.add(c2);
            s.setCategories(categories);
            Transaction t=session.getTransaction();
            t.begin();
            session.save(s);
            t.commit();
        }
        public @After void destory(){
            session.close();
            factory.close();
        }
    
    }

    转载请于明显处标明出处:

    https://www.cnblogs.com/AmyZheng/p/9322403.html

  • 相关阅读:
    Cookie同Session的关系 (2)
    Java Web应用开发概述
    Oracle客户端工具连接数据库服务器问题汇总
    java中使用JSCH包,SFTP及SSH2文件操作及远程命令执行
    javascript学习实录 之九(选择样式,改变文字效果) 刘小小尘
    用python给MP3加封面图片,修改作者,专辑等信息
    超像素分割技术发展情况梳理(Superpixel Segmentation)计算机视觉专题3
    android 应用程序的内存分析
    查询成绩
    sharepoint 2010 获取列表术语数据源方法
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9322403.html
Copyright © 2011-2022 走看看