Hibernate学习(五)
阅读原文时间:2023年07月11日阅读:1

自关联测试案例

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、映射文件

<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>

4、hibernate配置文件

<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>

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( "\\t" + 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( "\\t" + 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