Hibernate学习二(实体状态、缓存、多表关联)

目录

 

一、Hibernate实体的状态

1、状态介绍

2、瞬时状态 转 持久状态

3、持久状态转脱管状态(游离状态)

4、总结状态转换过程

二、缓存

1、一级缓存

2、快照----对一级缓存的数据进行备份

3、一级缓存的刷新

4、一级缓存的细节

5、其它API

三、Hibernate的多表关联关系映射

1、案例:一对多、多对一

2、设置外键维护的方式

3、一对多的查询和删除

4、级联保存和删除

 


一、Hibernate实体的状态

1、状态介绍

2、瞬时状态 转 持久状态

3、持久状态转脱管状态(游离状态)

4、总结状态转换过程

 

二、缓存

1、一级缓存

session级别的缓存

2、快照----对一级缓存的数据进行备份

3、一级缓存的刷新

会执行select语句一次、update语句一次

4、一级缓存的细节

HQL结果是会进行一级缓存,SQL的结果不会添加到一级缓存中

 @Test
    public void testFirstCache(){
        /**
         * 一级缓存的细节
         * HQL的结果会进行以及缓存,SQL的结果不一定添加到一级缓存中
         */
        Session session = HibernateUtil.openSession();
        /*
        查询所有数据
        */
      /*  //1、HQL
        Query queryq = session.createQuery("From User");
        List<User> list1 = queryq.list();
        System.out.println(list1);
        //2、sql
        SQLQuery query = session.createSQLQuery("select * from user");
        List list = query.list();
        System.out.println(list);*/


        //3、Criteria,会对数据进行一级缓存
        Criteria criteria = session.createCriteria(User.class);
        List list = criteria.list();

        System.out.println(list);
        //使用get方法查询一条数据,没有则为空
        User user = session.get(User.class, 4);//,Criteria查询后,会将数据添加到以及缓存中,查询主键为4的时候,首先在缓存中进行匹配,若没有匹配到对应的字段,然后再去数据库中查找
        System.out.println(user);
        //load方法:查询不存在的数据时会报错
        //比如:ObjectNotFoundException: No row with the given identifier exists: [com.dzg.domain.User#4]
        User loadUser = session.load(User.class, 3);
        System.out.println(loadUser);
    }

5、其它API

 

 @Test
    public void testSave(){
        Session session = HibernateUtil.openSession();
        session.getTransaction().begin();
        //刚new出来的对象时瞬时状态 ,经过save后,变成持久状态
        User user = new User("cacheName","1234");//瞬时态

        session.save(user);//持久态

        session.clear();//,移除缓存,user变成托管状态
        session.save(user);//执行insert语句

        session.getTransaction().commit();
        session.close();
    }
    @Test
    public void testPersist(){
        Session session = HibernateUtil.openSession();
        session.getTransaction().begin();
        //刚new出来的对象时瞬时状态 ,经过save后,变成持久状态
        User user = new User("persistName","5678");//瞬时态

        //1、使用persit方法进行保存,不能设置主键,否则报错user.setId(8);
        //javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.dzg.domain.User
        session.persist(user);//持久态

        session.getTransaction().commit();//注释掉该条语句,即不加事务,persist方法不会执行insert语句
        session.clear();
    }

save和persist方法的区别:

三、Hibernate的多表关联关系映射

1、案例:一对多、多对一

客户和订单表之间的关系

customer的配置文件

<?xml version="1.0"?>
<!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="com.dzg.domain.Customer" table="t_customer" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>

        <!--模型和表格的字段名一样,column可以不写-->
        <property name="name"/>
        <!--

            描述一对多的关系
                key中column写的是外键的名称
                one-to-many:一对多,里面写class,写多的一方

            inverse:其作用是指定由哪一方来维护关联关系
                    当一方指定了inverse = false(默认)
                    那么另一方,就负责关联关系

                    true:则外键有另一方维护
        -->
        <set name="orders" inverse="true">
            <key column="customerId"></key>
            <one-to-many class="com.dzg.domain.Order"></one-to-many>
        </set>

    </class>
</hibernate-mapping>

order的配置文件

<?xml version="1.0"?>
<!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="com.dzg.domain.Order" table="t_order" >
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <!--模型和表格的字段名一样,column可以不写-->
        <property name="name"/>
        <!--

            描述多对一的关系
                many-to-one:多对一,
                class:写一的一方
                column:写外键
        -->
        <many-to-one name="customer" class="com.dzg.domain.Customer" column="customerId"/>
    </class>
</hibernate-mapping>

测试添加数据:不需要自己创建表,可以使用创建会话的形式,对应的实体类属性JavaBean的写法,配置文件之间的关系配置好

可以自动创建表;


    //这会自动创建表
    @Test
    public void testCreateTable(){
        Session session = HibernateUtil.openSession();

        session.close();
    }

    @Test
    public void testOneToMany(){
        Session session = HibernateUtil.openSession();
        session.getTransaction().begin();//开启事务
        //保存数据
        //1、创建客户对象
        Customer customer = new Customer();
        customer.setName("张三");

        //2、创建两个订单
        Order order1 = new Order();
        order1.setName("轩辕剑");

        Order order2 = new Order();
        order2.setName("倚天剑");

        //3、维护客户与订单的关系
        order1.setCustomer(customer);
        order2.setCustomer(customer);

        //4、客户拥有订单
        customer.getOrders().add(order1);
        customer.getOrders().add(order2);

        //5、保存数据
        session.save(customer);//保存客户先
        session.save(order1);
        session.save(order2);
        session.getTransaction().commit();//提交事务

        session.close();
    }

2、设置外键维护的方式

3、一对多的查询和删除

 /**
     * 查询和删除
     */
    @Test
    public void testOneAndManyQuery(){
        Session session = HibernateUtil.openSession();
        //查询一对多
        /**
         * 默认情况下,只有当使用Customer的orders1的数据,会执行SQL语句
         */
        //1、查询客户
        Customer customer = session.get(Customer.class, 1);
        System.out.println("客户的名称为:"+customer.getName());
        //客户的所有订单
//        Query query = session.createQuery("From Order o where o.customer = ?");
        Set<Order> orders = customer.getOrders();
        for (Order order:
             orders) {
            System.out.println("订单的名称:"+order.getName());
        }
        session.close();
    }

    @Test
    public void testOneAndManyDelete(){
        Session session = HibernateUtil.openSession();
        //一对多的删除
        session.getTransaction().begin();
        Customer customer = session.get(Customer.class, 2);
        //如果要删除一对多,至少将订单的约束去除
        Set<Order> orders = customer.getOrders();
        for (Order order:
             orders) {
            order.setCustomer(null);//回执行update语句,将外键设置为null
        }
        session.delete(customer);
        session.getTransaction().commit();
        session.close();
    }

4、级联保存和删除

cascade级联

/**
     * 级联保存,保存A的时候,也保存B
     */
    @Test
    public void testOneToManySaveCascade(){
        Session session = HibernateUtil.openSession();
        session.getTransaction().begin();//开启事务
        //保存数据
        //1、创建客户对象
        Customer customer = new Customer();
        customer.setName("凯斯凯德");

        //2、创建两个订单
        Order order1 = new Order();
        order1.setName("数据一");

        Order order2 = new Order();
        order2.setName("数据二");

        //3、维护客户与订单的关系
        order1.setCustomer(customer);
        order2.setCustomer(customer);

        //4、客户拥有订单
        customer.getOrders().add(order1);
        customer.getOrders().add(order2);

        //5、保存数据
        session.save(customer);//保存客户,也保存订单
     /*
        设置 <set name="orders" inverse="true" cascade="save-update">中
        cascade="save-update"则会级联保存数据
        session.save(order1);
        session.save(order2);*/
        session.getTransaction().commit();//提交事务

        session.close();
    }


    @Test
    public void testOneAndManyDeleteCascade(){
        Session session = HibernateUtil.openSession();
        //一对多的删除
        session.getTransaction().begin();
        Customer customer = session.get(Customer.class, 3);
        //配置了级联删除后,删除customer的同时将其对应的订单数据也删除
        //<set name="orders" inverse="true" cascade="delete">  ---->cascade="delete"
        /**执行删除的操作,先删除有外键的订单表内的相关数据,然后再删除客户表的数据
         Hibernate:
             select
             customer0_.id as id1_0_0_,
             customer0_.name as name2_0_0_
             from
             t_customer customer0_
             where
             customer0_.id=?
         Hibernate:
             select
             orders0_.customerId as customer3_1_0_,
             orders0_.id as id1_1_0_,
             orders0_.id as id1_1_1_,
             orders0_.name as name2_1_1_,
             orders0_.customerId as customer3_1_1_
             from
             t_order orders0_
             where
             orders0_.customerId=?
         Hibernate:
             delete
             from
             t_order
             where
             id=?
         Hibernate:
             delete
             from
             t_order
             where
             id=?
         Hibernate:
             delete
             from
             t_customer
             where
             id=?
         */
        session.delete(customer);
        session.getTransaction().commit();
        session.close();
    }

孤儿删除:

@Test
    public void testOneAndManyDeleteOrphan(){
        Session session = HibernateUtil.openSession();
        //一对多的删除
        session.getTransaction().begin();
        //获取客户
        Customer customer = session.get(Customer.class, 1);

        //删除客户1的所有订单,但是客户仍然存在

        //孤儿删除步骤,1、设置cascade=“delete-orphan” 2、把订单从Customer的set集合中删除,移除客户的订单内的数据

        Set<Order> orders = customer.getOrders();
        Iterator<Order> iterator = orders.iterator();
        while (iterator.hasNext()){
            iterator.next();// 取出下一个元素
            iterator.remove();
        }
//        session.delete(customer);

        session.getTransaction().commit();
        session.close();
    }

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值