自关联测试案例

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

Hibernate学习(五)的更多相关文章

  1. hibernate学习五(关系映射多对一与一对多)

    一.多对一 多对一(或者一对多):在学生与老师的情况下,一个老师可以教多个学生,但一个学生只能被教一个老师教: 对于类:在多的那方拥有一的那方的一个实体 二.修改student.java和teache ...

  2. hibernate 学习 五 hibernate核心接口

    一 Configuration接口 Configuration对象只存在于系统的初始化阶段.配置相关. 配置文件可以使用默认的路径,也可以指定路径. Configuration config = ne ...

  3. Hibernate学习(五)Hibernate 多对多映射

    说到多对多关系,印象最深刻的就是大学的选修课.一个学生可以选修多门课程,一门课程可以有多个学生选修,学生所选的每一门课程还有成绩.这个场景的E-R图如下: 对于多对多的关系,我们通常会抽出一张中间表( ...

  4. Hibernate学习五----------组件属性

    © 版权声明:本文为博主原创文章,转载请注明出处 实例 1.项目结构 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...

  5. hibernate学习五 Hibernate补充

    1  MiddleGenIDE可以生成映射类和映射文件. 2

  6. Hibernate学习笔记-Hibernate HQL查询

    Session是持久层操作的基础,相当于JDBC中的Connection,通过Session会话来保存.更新.查找数据.session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库 ...

  7. Hibernate学习---缓存机制

    前言:这些天学习效率比较慢,可能是手头的事情比较多,所以学习进度比较慢. 在之前的Hibernate学习中,我们无论是CURD,对单表查询还是检索优化,我们好像都离不开session,session我 ...

  8. Hibernate学习之——搭建log4j日志环境

    昨天讲了Hibernate开发环境的搭建以及实现一个Hibernate的基础示例,但是你会发现运行输出只有sql语句,很多输出信息都看不见.这是因为用到的是slf4j-nop-1.6.1.jar的实现 ...

  9. Hibernate学习笔记(二)

    2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...

  10. Hibernate学习笔记(一)

    2016/4/18 19:58:58 Hibernate学习笔记(一) 1.Hibernate框架的概述: 就是一个持久层的ORM框架. ORM:对象关系映射.将Java中实体对象与关系型数据库中表建 ...

随机推荐

  1. C语言 puts

    C语言 puts #include <stdio.h> int puts(const char *s); 功能:标准设备输出s字符串,在输出完成后自动输出一个'\n'. 参数: s:字符串 ...

  2. ffmpeg 音频常用命令

    ffmpeg的使用方式: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}... Stream ...

  3. Systemd 学习

    转:http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html 原文链接:https://www.jianshu.com ...

  4. codeforces 711 D.Directed Roads(tarjan 强连通分量 )

    题目链接:http://codeforces.com/contest/711/problem/D 题目大意:Udayland有一些小镇,小镇和小镇之间连接着路,在某些区域内,如果从小镇Ai开始,找到一 ...

  5. 左偏树 (p3261) 对我来说是一道进阶题

    题意:有n座城池,m个人: 每座城池有一个耐久度: 每座城池有一个父亲城池(肯定会形成一棵树),还有flag base (这个看题意) 每个人有一个战力值和一个开始进攻的城池序号: 问:1.每个城池能 ...

  6. hdu 4280 最大流 sap模板

    给你岛的坐标求最西边到最东边的最大流 /* 最大流模板 sap */ #include<stdio.h> #include<string.h> #include<algo ...

  7. 【PAT甲级】1112 Stucked Keyboard (20分)(字符串)

    题意: 输入一个正整数K(1<K<=100),接着输入一行字符串由小写字母,数字和下划线组成.如果一个字符它每次出现必定连续出现K个,它可能是坏键,找到坏键按照它们出现的顺序输出(相同坏键 ...

  8. 排序:ORDER BY

    1.按照字段值进行排序: 语法:order by 字段 升序|降序 (asc|desc) 默认情况下为“升序” asc.asc=ascending 升 desc=descending 降 2.允许多字 ...

  9. python中 使用join()方法

    使用join()方法 对各种数据类型中元的素进行合并拼接 "连接符".join(列表或元组或字符串或字典) 返回的是一个使用连接符进行拼接的字符串 如果对象是列表,元组,就是以一个 ...

  10. HDU 1237 简单计算器(栈+stringstream)

    提供几份代码,这题的输入可以用stringsteam处理,先处理乘除后处理加减,正常思路,但是后面统计加减法的时候,对栈的运用错了,我用的时候相当于给它多加了几个括号就错了. 正确的简单解法就是,加法 ...