Hibernate--day02

作者: 键盘瞎 | 来源:发表于2017-02-11 16:55 被阅读70次

非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿


记笔记啊记笔记

持久化类的状态

持久化类三种状态

持久化类有三种状态,区分不同的状态,使用两种操作区分:

​ 第一个 判断对象是否有oid

​ 第二个 判断对象是否与session相关联

1、瞬时态

没有oid,没有与session相关联

User user = new User();
user.setUsername("xxx");
user.setBirthday(new Date());

2、持久态

有oid,与session相关联

User user = (User)session.get(User.class, 1);

3、托管态

有oid,没有与session相关联

User user = new User();
user.setId(1);
user.setUsername("大黄蜂");

三种状态之间转换

三种状态之间转换

瞬时态

​ 转换成持久态:调用save方法,saveOrUpdate方法实现

​ 状态成脱管态:设置oid值

持久态

​ 转换成瞬时态:调用delete方法实现

​ 转换成脱管态:调用session里面的close方法实现

脱管态

​ 转换成瞬时态:设置oid值为空

​ 转换成持久态:调用update和saveOrUpdate方法实现

Hibernate的一级缓存

什么是缓存

把数据不放到文件系统中,放到系统内存中,可以直接从内存中获取数据,提高获取数据的效率

Hibernate的缓存

Hibernate的一级缓存

在Hibernate中的一级缓存默认是打开的,一级缓存使用的范围是session范围的。从session创建,到session关闭的过程。如果session关闭了,那么一级缓存也就关闭了。

Hibernate的二级缓存

在Hibernate中的二级缓存默认不是打开的,手动设置才可以使用。二级缓存使用范围是sessionFactory范围的二级缓存。

验证一级缓存的存在

第一个操作:首先添加记录,添加完成后,根据oid进行查询

//添加操作
User user = new User();
user.setUsername("岳不群");
user.setBirthday(new Date());

//调用save方法
Serializable id = session.save(user);

//根据返回的id值查询
User u = (User) session.get(User.class, id);
System.out.println(u);

第一次执行添加操作,发送sql语句,实现添加数据到数据库

第二次根据添加之后返回的id进行查询,没有查询数据库,而是查询一级缓存内容

sql语句

第二个操作:第一次查询id是1的记录,第二次再次查询id值是1的记录

//第一次查询id值是1的记录
User user1 = (User) session.get(User.class, 1);
System.out.println(user1);

//第二次查询id值是1的记录
User user2 = (User) session.get(User.class, 1);
System.out.println(user2);

第一次查询数据库获取数据,第二次没有查询数据库,查询一级缓存的内容

sql语句

持久态自动更新数据库

//查询id是2的记录
//持久态
User user = (User) session.get(User.class, 2);
//设置要修改的值
user.setUsername("哈哈");

//调用update
//session.update(user);

不需要调用update方法实现修改

一级缓存的快照区(副本)

//查询id是2的记录
//持久态
User user = (User) session.get(User.class, 2);
//设置要修改的值
user.setUsername("哈哈");

//调用update
//session.update(user);

首先根据id查询用户数据,返回user是持久态对象。

首先把返回的持久态user对象放到一级缓存中,另外,把user对象复制一份,再放到一级缓存对应的快照区。

设置了持久态对象里面的值的时候(修改了user里面的值),执行之后

首先,同步更新一级缓存中的内容;其次,但是不会更新对应快照区的内容

提交了事务之后,实现比较一级缓存和快照区的内容是否相同,如果不相同,把一级缓存中的内容更新到数据库里

一级缓存使用Java的集合存储,使用map集合

Key是一级缓存,Value是快照区

图一 图二

操作持久化类的方法

常用的方法

描述 方法
添加 save()
修改 update()
删除 delete()
根据id查询 get()、load()
添加或修改 saveOrUpdate()

saveOrUpdate方法使用(保存、修改)

这个方法可以实现添加操作,也可以实现修改操作。根据实体类的不同状态实现不同的操作

第一个 实现添加操作

当实体类状态是瞬时态时候,调用这个方法实现添加操作

//实现添加操作
//瞬时态
User user = new User();
user.setUsername("东方不败");
user.setBirthday(new Date());

//执行saveOrUpdate方法
session.saveOrUpdate(user);

第二个 实现修改操作

持久化类状态是持久态和脱管态时,实现修改操作

//实现修改操作
User user = (User) session.get(User.class, 1);
user.setUsername("令狐冲");

//调用方法
session.saveOrUpdate(user);

//脱管态
User user = new User();
user.setId(2);
user.setUsername("任盈盈");
user.setBirthday(new Date());

//调用方法
session.saveOrUpdate(user);

load方法使用(延迟查询)

load方法和get方法相同,根据id查询数据,返回对象

区别:

​ get方法:立刻查询,执行方法之后,马上查询数据库

​ load方法:延迟查询,执行load方法之后,不会马上查询数据库,得到返回对象里面的值的时候才会去查询数据库

//get方法查询
User user = (User) session.get(User.class, 1);
System.out.println(user);

执行get方法之后,立刻发送语句查询数据库

//load方法查询
User user = (User) session.load(User.class, 3);
System.out.println(user.getId());
System.out.println(user.getUsername());

执行load方法之后,没有发送sql语句查询数据库,返回实体类对象中只有一个id值,但是得到实体类对象中除了id值之外其他值的时候,才会发送sql语句查询数据库

Hibernate的一对多关系映射

内容回顾

表与表之间关系

一对多

范例:一个客户可以有多个订单,一个订单只能属于一个客户

建表原则:在多的那一端创建字段作为外键,指向一的那一端的主键

示例

多对多

范例:一定订单里面可以有多个商品,一个商品可以属于多个订单;一个学生可以选择多个课程,一个课程可以被多个学生选择

建表原则:创建第三张表,至少有两个字段,左为外键,指向另外两张表的主键

示例

一对一

范例:一个公司对应一个注册地址,一个注册地址只能有一个公司

Hibernate的一对多关系映射

第一步 创建客户和订单的实体类

第二步 让实体类之间相互表示

客户实体类 Customer

package cn.itcast.onetomany;

import java.util.HashSet;
import java.util.Set;

/**
 * 客户实体类
 */
public class Customer {

    private Integer cid;
    private String cname;
    private String address;
    
    //在客户里面表示所有的订单
    //第二步使用集合表示 set集合  set集合有序的  并且内容不重复
    private Set<Orders> setOrders = new HashSet<Orders>();
    public Set<Orders> getSetOrders() {
        return setOrders;
    }
    public void setSetOrders(Set<Orders> setOrders) {
        this.setOrders = setOrders;
    }
    public Integer getCid() {
        return cid;
    }
    public void setCid(Integer cid) {
        this.cid = cid;
    }
    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }   
}

订单实体类 Orders

package cn.itcast.onetomany;
/**
 * 订单实体类
 */
public class Orders {

    private Integer oid;
    private String oname;
    private Integer price;
    
    //第二步表示订单所属的客户
    private Customer customer;
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    public Integer getOid() {
        return oid;
    }
    public void setOid(Integer oid) {
        this.oid = oid;
    }
    public String getOname() {
        return oname;
    }
    public void setOname(String oname) {
        this.oname = oname;
    }
    public Integer getPrice() {
        return price;
    }
    public void setPrice(Integer price) {
        this.price = price;
    }
    
}

第三步 使用映射文件配置一对多关系(两个映射文件)

创建客户映射文件 Customer.hbm.xml 一的一方

<?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>
    <!--name值Customer实体类的全路径   table表名 随便写-->
    <class name="cn.itcast.onetomany.Customer" table="CUSTOMER">
        <!-- 配置cid; name值与实体类一致column随意-->
        <id name="cid" column="CID">
            <!-- 配置生成策略 -->
            <generator class="native"></generator>
        </id>
        <!-- 其他的属性 name值与实体类一致column随意-->
        <property name="cname" column="CNAME"></property>
        <property name="address" column="ADDRESS"></property>
        <!-- 配置客户的所有的订单
            set标签上面的name:客户里面所有订单的set集合的名称  
         -->
         <set name="setOrders">
            <!-- 一对多里面,外键双向维护关系
                column: 外键名称  一致
             -->
            <key column="coid"></key>
            <!-- 指定订单实体类位置 
                class: 订单实体类全路径
            -->
            <one-to-many class="cn.itcast.onetomany.Orders"></one-to-many>
         </set>
    </class>
</hibernate-mapping>

创建订单映射文件夹 Order.hbm.xml 多的一方

<?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>
    <!--name值Customer实体类的全路径   table表名 随便写-->
     <class name="cn.itcast.onetomany.Orders" table="ORDERS">
         <!-- 配置oid; name值与实体类一致column随意-->
        <id name="oid" column="OID">
            <!-- 配置生成策略 -->
            <generator class="native"></generator>
        </id>
         <!-- 其他的属性 name值与实体类一致column随意-->
        <property name="oname" column="ONAME"></property>
        <property name="price" column="PRICE"></property>
        <!-- 配置订单所属哪个用户 one many  
            name: 在订单实体类定义用户类的属性名称  
            class: 用户实体类的全路径
            column: 外键名称
        -->
        <many-to-one name="customer"
        class="cn.itcast.onetomany.Customer" column="coid" ></many-to-one>
    </class>
</hibernate-mapping>

第四步 需要把配置的映射文件引入到核心文件中

创建核心配置文件 hibernate.cfg.xml

<?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:///hibernate_day02
    </property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">root</property>
    <!-- 配置数据库的方言 
        比如在mysql里面有关键字  limit ,只能使用在mysql里面
        让hibernate识别到不同数据库自己特有的语句
    -->
    <property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    </property>

    <!-- 配置hibernate的相关信息 -->
    <!-- 是否显示底层的sql语句 -->
    <property name="hibernate.show_sql">true</property>
    <!-- 是否格式化sql语句 -->
    <property name="hibernate.format_sql">true</property>
    <!-- hibernate会帮自己创建数据库表,默认不会创建,需要配置 
        值 update: 如果数据库里面不存在表,创建;如果已经存在,更新
    -->
    <property name="hibernate.hbm2ddl.auto">update</property>
    <!-- 引入映射配置文件 -->
    <mapping resource="cn/itcast/onetomany/Customer.hbm.xml" />
    <mapping resource="cn/itcast/onetomany/Orders.hbm.xml" />

</session-factory>
</hibernate-configuration>

第五步 创建工具类运行建表

创建工具类HibernateUtils工具类,并添加main方法

package cn.itcast.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * 创建sessionFactory对象
 */
public class HibernateUtils {
    
    static Configuration cfg = null;
    static SessionFactory sessionFactory  = null;
    //静态代码块
    static {
        cfg = new Configuration();
        cfg.configure();
        //创建sessionFactory
        sessionFactory  = cfg.buildSessionFactory();
    }

    //提供得到Session的方法
    public static Session getSession() {
        Session session = sessionFactory.openSession();
        return session;
    }
    
    public static void main(String[] args) {
        
    }
}

一对多的级联保存(同时向多个表里添加数据)

有客户,有订单。比如添加一个客户,同时添加这个客户对应多个订单

原始方式:(开发一般不用)

创建TestOneToMany类

package cn.itcast.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;

/**
 * 演示级联保存操作
 */
public class TestOneToMany {
    
    @Test
    public void testSave1() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            //第一步创建不同对象
            //添加一个用户
            Customer c1 = new Customer();
            c1.setCname("小奥");
            c1.setAddress("美国");
            
            //添加用户对于的两个订单
            Orders o1 = new Orders();
            o1.setOname("飞机");
            o1.setPrice(10);
            
            Orders o2 = new Orders();
            o2.setOname("航空母舰");
            o2.setPrice(20);
            //第二步互相表示
            //设置用户和订单之间的关联关系
            //表示用户里面有两个订单 
            //把两个订单放到customer的set集合里面
            c1.getSetOrders().add(o1);
            c1.getSetOrders().add(o2);
            
            //表示两个订单所属的用户
            o1.setCustomer(c1);
            o2.setCustomer(c1);
            //第三步添加这些对象
            //调用方法保存
            session.save(c1);
            session.save(o1);
            session.save(o2);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }
}

这种方法如果只保存用户 或者只保存订单,不能进行操作,出现异常

异常

级联保存另外实现方式(都使用)

设置互相表示的关系的时候,只需要设置一方,可以直接保存一方就可以了

但是在哪一方进行保存,需要在哪一方配置cascade="save-update"

通过客户进行保存

创建TestOneToMany测试类

package cn.itcast.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;

/**
 * 演示级联保存操作
 */
public class TestOneToMany {

//演示通过用户进行保存
    @Test
    public void testSave2() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            //第一步 创建实体类对象
            //添加一个用户
            Customer c1 = new Customer();
            c1.setCname("小温");
            c1.setAddress("中国");
            
            //添加用户对于的两个订单
            Orders o1 = new Orders();
            o1.setOname("篮球");
            o1.setPrice(30);
            
            Orders o2 = new Orders();
            o2.setOname("足球");
            o2.setPrice(20);
            //第二步 设置用户所有的订单
            //设置用户里面的所有的订单
            c1.getSetOrders().add(o1);
            c1.getSetOrders().add(o2);
            //第三步 直接保存用户对象
            //保存用户
            session.save(c1);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }
}   

第四步 在用户的映射文件中配置 Customer.hbm.xml

<?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="cn.itcast.onetomany.Customer" table="CUSTOMER">
        <!-- 配置oid -->
        <id name="cid" column="CID">
            <!-- 配置生成策略 -->
            <generator class="native"></generator>
        </id>
        <!-- 其他的属性 -->
        <property name="cname" column="CNAME"></property>
        <property name="address" column="ADDRESS"></property>
        <!-- 配置客户的所有的订单
            set标签上面的name:客户里面所有订单的set集合的名称  
            cascade="save-update" : 级联保存        
            cascade="delete"
         -->
         <set name="setOrders" cascade="save-update">
            <!-- 一对多里面,外键双向维护关系
                column: 外键名称
             -->
            <key column="coid"></key>
            <!-- 指定订单实体类位置 
                class: 订单实体类全路径
            -->
            <one-to-many class="cn.itcast.onetomany.Orders"></one-to-many>
         </set>
    </class>
</hibernate-mapping>

通过订单进行保存

创建TestOneToMang测试类

package cn.itcast.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;

/**
 * 演示级联保存操作
 */
public class TestOneToMany {

//演示通过订单进行保存
    @Test
    public void testSave3() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            //第一步 创建实体类对象
            //添加一个用户
            Customer c1 = new Customer();
            c1.setCname("小江");
            c1.setAddress("中国");
            
            //添加用户对于的两个订单
            Orders o1 = new Orders();
            o1.setOname("眼镜");
            o1.setPrice(30);
            
            Orders o2 = new Orders();
            o2.setOname("汽车2");
            o2.setPrice(20);
            //第二步 设置用户所有的订单
            //设置订单所属的用户
            o1.setCustomer(c1);
            o2.setCustomer(c1);
            //第三步 直接保存用户对象
            //保存订单
            session.save(o1);
            session.save(o2);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }
}

第四步 在订单的映射文件中配置 Order.hbm.xml

<?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="cn.itcast.onetomany.Orders" table="ORDERS">
        <id name="oid" column="OID">
            <generator class="native"></generator>
        </id>
        <property name="oname" column="ONAME"></property>
        <property name="price" column="PRICE"></property>
        <!-- 配置订单所属哪个用户 one many  
            name: 在订单实体类定义用户类的属性名称
            class: 用户实体类的全路径
            column: 外键名称
            cascade="save-update" : 级联保存
        -->
        <many-to-one name="customer" 
                class="cn.itcast.onetomany.Customer" column="coid" cascade="save-update"></many-to-one>
    </class>
</hibernate-mapping>

一对多的级联删除(同时删除多个表里面管理的数据)

不配置方法用户删除但是只是把订单变为null(不用)

创建TestOneToMany类

package cn.itcast.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;

/**
 * 演示级联删除操作
 */
public class TestOneToMany {

    //级联删除操作
    @Test
    public void testDelete1() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            
            //删除cid值是1的记录
            Customer c1 = (Customer) session.get(Customer.class, 3);
            //删除操作
            session.delete(c1);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }
}

根据用户删除配置方法(都用)

在hibernate的一对多的进行删除操作时候

比如删除用户,首先把用户关联的订单的外键设置为NULL,再删除用户

1、创建TestOneToMany类

package cn.itcast.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;

/**
 * 演示级联删除操作
 */
public class TestOneToMany {

//级联删除操作
    @Test
    public void testDelete1() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            
            //删除cid值是1的记录
            Customer c1 = (Customer) session.get(Customer.class, 3);
            //删除操作
            session.delete(c1);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }
}

2、在用户的映射文件中配置 hibernate.hbm.xml

<?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="cn.itcast.onetomany.Customer" table="CUSTOMER">
        <!-- 配置oid -->
        <id name="cid" column="CID">
            <!-- 配置生成策略 -->
            <generator class="native"></generator>
        </id>
        <!-- 其他的属性 -->
        <property name="cname" column="CNAME"></property>
        <property name="address" column="ADDRESS"></property>
        <!-- 配置客户的所有的订单
            set标签上面的name:客户里面所有订单的set集合的名称  
            cascade="save-update" : 级联保存        
            cascade="delete"
            cascade="save-update,delete"多个属性用,号隔开
         -->
         <set name="setOrders" cascade="save-update,delete">
            <!-- 一对多里面,外键双向维护关系
                column: 外键名称
             -->
            <key column="coid"></key>
            <!-- 指定订单实体类位置 
                class: 订单实体类全路径
            -->
            <one-to-many class="cn.itcast.onetomany.Orders"></one-to-many>
         </set>
    </class>
</hibernate-mapping>    

根据订单删除配置方法(不用)

1、创建TestOneToMany类

package cn.itcast.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;

/**
 * 演示级联删除操作
 */
public class TestOneToMany {

    //级联删除操作
    @Test
    public void testDelete2() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            
            //删除oid值是1的订单
            Orders o1 = (Orders) session.get(Orders.class, 1);
            //删除操作
            session.delete(o1);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }
}

2、在订单的映射文件中配置 Orders.hbml.xml

<?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="cn.itcast.onetomany.Orders" table="ORDERS">
        <id name="oid" column="OID">
            <generator class="native"></generator>
        </id>
        <property name="oname" column="ONAME"></property>
        <property name="price" column="PRICE"></property>
        <!-- 配置订单所属哪个用户 one many  
            name: 在订单实体类定义用户类的属性名称
            class: 用户实体类的全路径
            column: 外键名称
            delete删除
        -->
        <many-to-one name="customer" 
                class="cn.itcast.onetomany.Customer" column="coid" cascade="delete"></many-to-one>
    </class>
</hibernate-mapping>

Hibernate的多对多关系映射

第一步 创建实体类

第二步 让学生和课程的实体类相关联

学生类 student

package cn.itcast.manytomany;

import java.util.HashSet;
import java.util.Set;

public class Student {

    private Integer sid;
    private String sname;
    private String address;
    
    //第二步 学生选择课程 ,一个学生可以选择多门课程
    private Set<Course> setCourse = new HashSet<Course>();
    public Set<Course> getSetCourse() {
        return setCourse;
    }
    public void setSetCourse(Set<Course> setCourse) {
        this.setCourse = setCourse;
    }
    public Integer getSid() {
        return sid;
    }
    public void setSid(Integer sid) {
        this.sid = sid;
    }
    public String getSname() {
        return sname;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}

课程类 Course

package cn.itcast.manytomany;

import java.util.HashSet;
import java.util.Set;

public class Course {

    private Integer cid;
    private String cname;
    
    // 第二步  在课程端表示被哪些学生选择,一门课程可以被多个学生选择
    private Set<Student> setStudent = new HashSet<Student>();
    public Set<Student> getSetStudent() {
        return setStudent;
    }
    public void setSetStudent(Set<Student> setStudent) {
        this.setStudent = setStudent;
    }
    public Integer getCid() {
        return cid;
    }
    public void setCid(Integer cid) {
        this.cid = cid;
    }
    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    
}

第三步 使用映射文件配置多对多关系(两个映射文件)

学生映射文件 student.hbm.xml

<?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="cn.itcast.manytomany.Student" table="STUDENT">
        <id name="sid" column="SID">
            <generator class="native"></generator>
        </id>
        <property name="sname"></property>
        <property name="address"></property>
        <!-- 配置学生选择的多门课程 -->
        <set name="setCourse" table="STU_COURSE">
            <!-- 当前配置的实体类  student 在第三张表里面外键名称-->
            <key column="s_id"></key>
            <!-- class: 课程全路径
                column:课程表在第三张表外键名称
             -->
            <many-to-many class="cn.itcast.manytomany.Course" column="c_id"></many-to-many>
        </set>
    </class>    
</hibernate-mapping>   

课程映射文件 Course.hbm.xml

<?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="cn.itcast.manytomany.Course" table="COURSE">
         <id name="cid" column="CID">
            <generator class="native"></generator>
         </id>
         <property name="cname"></property>
         <!-- 配置课程被哪些学生选择 -->
         <set name="setStudent" table="STU_COURSE">
            <!-- 当前配置的课程 course 在第三张表里面的外键名称 -->
            <key column="c_id"></key>
            <!-- 
                class: 学生的全路径
                column:学生表在第三张表外键名称
             -->
            <many-to-many class="cn.itcast.manytomany.Student" column="s_id"></many-to-many>
         </set>
    </class>    
</hibernate-mapping>

第四步 需要把配置的映射文件引入到核心配置文件中

核心配置文件 hibernate.cfg.xml

<?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:///hibernate_day02
    </property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">root</property>
    <!-- 配置数据库的方言 
        比如在mysql里面有关键字  limit ,只能使用在mysql里面
        让hibernate识别到不同数据库自己特有的语句
    -->
    <property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    </property>

    <!-- 配置hibernate的相关信息 -->
    <!-- 是否显示底层的sql语句 -->
    <property name="hibernate.show_sql">true</property>
    <!-- 是否格式化sql语句 -->
    <property name="hibernate.format_sql">true</property>
    <!-- hibernate会帮自己创建数据库表,默认不会创建,需要配置 
        值 update: 如果数据库里面不存在表,创建;如果已经存在,更新
    -->
    <property name="hibernate.hbm2ddl.auto">update</property>
    <!-- 引入映射配置文件 -->
    <mapping resource="cn/itcast/manytomany/Course.hbm.xml" />
    <mapping resource="cn/itcast/manytomany/Student.hbm.xml" />

</session-factory>
</hibernate-configuration>

第五步 创建工具类运行建表

HibernateUtils工具类 main方法

package cn.itcast.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * 创建sessionFactory对象
 */
public class HibernateUtils {
    
    static Configuration cfg = null;
    static SessionFactory sessionFactory  = null;
    //静态代码块
    static {
        cfg = new Configuration();
        cfg.configure();
        //创建sessionFactory
        sessionFactory  = cfg.buildSessionFactory();
    }

    //提供得到Session的方法
    public static Session getSession() {
        Session session = sessionFactory.openSession();
        return session;
    }
    
    public static void main(String[] args) {
        
    }
}

多对多级联保存

创建TestManyToMany类

package cn.itcast.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.manytomany.Course;
import cn.itcast.manytomany.Student;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;

/**
 * 多对多操作
 */
public class TestManyToMany {
    //根据课程保存
    @Test
    public void testSave2() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            
            //添加两个学生
            Student s1 = new Student();
            s1.setSname("tom");
            s1.setAddress("usa");
            
            Student s2 = new Student();
            s2.setSname("jack");
            s2.setAddress("japan");
            
            //添加课程
            Course c1 = new Course();
            c1.setCname("ui设计");
            
            Course c2 = new Course();
            c2.setCname("java开发");
            
            Course c3 = new Course();
            c3.setCname("韩语");
            
            //根据课程保存
            // s1 -- c1/c2
            // s2 -- c1/c3
            c1.getSetStudent().add(s1);
            c1.getSetStudent().add(s2);
            c2.getSetStudent().add(s1);
            c3.getSetStudent().add(s2);
            
            //保存
            session.save(c1);
            session.save(c2);
            session.save(c3);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }
    //根据学生保存
    @Test
    public void testSave1() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            
            //添加两个学生
            Student s1 = new Student();
            s1.setSname("lucy");
            s1.setAddress("china");
            
            Student s2 = new Student();
            s2.setSname("mary");
            s2.setAddress("japan");
            
            //添加课程
            Course c1 = new Course();
            c1.setCname("汽车修理");
            
            Course c2 = new Course();
            c2.setCname("美容美发");
            
            Course c3 = new Course();
            c3.setCname("厨师");
            
            //根据学生保存
            // s1 --- c1 / c2
            // s2 ---- c2 / c3
            s1.getSetCourse().add(c1);
            s1.getSetCourse().add(c2);
            s2.getSetCourse().add(c2);
            s2.getSetCourse().add(c3);
            
            //保存
            session.save(s1);
            session.save(s2);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }   
}

根据学生保存 配置学生映射student.hbm.xml

<?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="cn.itcast.manytomany.Student" table="STUDENT">
        <id name="sid" column="SID">
            <generator class="native"></generator>
        </id>
        <property name="sname"></property>
        <property name="address"></property>
        <!-- 配置学生选择的多门课程     cascade="save-update" -->
        <set name="setCourse" table="STU_COURSE" cascade="save-update">
            <!-- 当前配置的实体类  student 在第三张表里面外键名称-->
            <key column="s_id"></key>
            <!-- class: 课程全路径
                column:课程表在第三张表外键名称
             -->
            <many-to-many class="cn.itcast.manytomany.Course" column="c_id"></many-to-many>
        </set>
    </class>    
</hibernate-mapping>

根据课程保存 Courses.hbm.xml

<?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="cn.itcast.manytomany.Course" table="COURSE">
         <id name="cid" column="CID">
            <generator class="native"></generator>
         </id>
         <property name="cname"></property>
         <!-- 配置课程被哪些学生选择   cascade="save-update"-->
         <set name="setStudent" table="STU_COURSE" cascade="save-update">
            <!-- 当前配置的课程 course 在第三张表里面的外键名称 -->
            <key column="c_id"></key>
            <!-- 
                class: 学生的全路径
                column:学生表在第三张表外键名称
             -->
            <many-to-many class="cn.itcast.manytomany.Student" column="s_id"></many-to-many>
         </set>
    </class>    
</hibernate-mapping>

多对多级联删除(不用)

创建TestManyToMany类

package cn.itcast.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.manytomany.Course;
import cn.itcast.manytomany.Student;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;

/**
 * 多对多操作
 */
public class TestManyToMany {
    //多对多删除
    @Test
    public void testDelete() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();
            
            //sid=1的学生删除
            Student s = (Student) session.get(Student.class, 1);
            session.delete(s);
            
            tx.commit();
        }catch(Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
        }
    }
}

根据学生删除 配置学生映射student.hbm.xml

<?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="cn.itcast.manytomany.Student" table="STUDENT">
        <id name="sid" column="SID">
            <generator class="native"></generator>
        </id>
        <property name="sname"></property>
        <property name="address"></property>
        <!-- 配置学生选择的多门课程   cascade="delete"-->
        <set name="setCourse" table="STU_COURSE" cascade="save-update,delete">
            <!-- 当前配置的实体类  student 在第三张表里面外键名称-->
            <key column="s_id"></key>
            <!-- class: 课程全路径
                column:课程表在第三张表外键名称
             -->
            <many-to-many class="cn.itcast.manytomany.Course" column="c_id"></many-to-many>
        </set>
    </class>    
</hibernate-mapping>

根据课程删除 配置课程映射Courses.hbml.xml

<?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="cn.itcast.manytomany.Course" table="COURSE">
         <id name="cid" column="CID">
            <generator class="native"></generator>
         </id>
         <property name="cname"></property>
         <!-- 配置课程被哪些学生选择   cascade="delete"-->
         <set name="setStudent" table="STU_COURSE" cascade="save-update,delete">
            <!-- 当前配置的课程 course 在第三张表里面的外键名称 -->
            <key column="c_id"></key>
            <!-- 
                class: 学生的全路径
                column:学生表在第三张表外键名称
             -->
            <many-to-many class="cn.itcast.manytomany.Student" column="s_id"></many-to-many>
         </set>
    </class>    
</hibernate-mapping>

相关文章

  • Hibernate--day02

    非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿记笔记啊记笔记 持久化类的状态 持久化类三种状态 持久...

网友评论

    本文标题:Hibernate--day02

    本文链接:https://www.haomeiwen.com/subject/phcoittx.html