Hibernate概念篇(一)

Hibernate事务

Hibernate的任何对数据有改动的操作,都应该被放在事务里面。
在事务中的多个操作行为,要么都成功,要么都失败

效果

在这里插入图片描述

在同一个事务中做了两件事情

  1. 删除id=1的产品
  2. 修改id=2的产品,使得其产品名称超过了数据库中设置的长度30. 提交事务。

第二个任务失败了,但是因为在同一个事务中,所以第一个任务也没有生效。因此id=1的产品,依然保留下来了

代码

public class TestHibernate {
    public static void main(String[] args) {
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
        Session s = sf.openSession();
        s.beginTransaction();
 
        Product p = (Product) s.get(Product.class, 1);
        s.delete(p);
 
        Product p2 = (Product) s.get(Product.class, 2);
        p2.setName("长度超过30的字符串作为产品名称长度超过30的字符串作为产品名称长度超过30的字符串作为产品名称长度超过30的字符串作为产品名称");
        s.update(p2);
 
        s.getTransaction().commit();
        s.close();
        sf.close();
    }
}

Hibernate属性的延迟加载(懒加载)

当使用load的方式来获取对象的时候,只有访问了这个对象的属性,hibernate才会到数据库中进行查询。否则不会访问数据库

代码

public class TestHibernate {
    public static void main(String[] args) {
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
        Session s = sf.openSession();
        s.beginTransaction();
     
        Product p = (Product)s.load(Product.class, 1);   //使用load的方式来获取对象
        System.out.println("log1");
        System.out.println(p.getName());       //访问产品名称属性
        System.out.println("log2");
 
        s.getTransaction().commit();
        s.close();
        sf.close();
    }
}

效果
在这里插入图片描述

由上图可见在打印log1之前,是不会打印出sql语句的,只有在访问属性“getName()"的时候,才会访问数据库,并打印log2

要注意的是:
使用load访问对象时,获得该对象的id(即主属性),不访问数据库;
当访问非主属性(name)之类的就会访问数据库,执行数据库查询了;

package Test;
import hibernate.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class UserDao {
    static SessionFactory sf = new Configuration().configure().buildSessionFactory();
    static Session s = sf.openSession();
     
    public User read() {
        Transaction t = s.beginTransaction();         
        
        User user = (User) s.get(User.class, 1);
        System.out.println(user.getId() + "\t" + user.getName());
         
        t.commit();
        return user;
    }
     
    public static User load() {
        Transaction t = s.beginTransaction();
        for (int i = 0; i < 10; i++) {
            User p = new User();
            p.setName("User"+i);
            s.save(p);         
        }
        User user = (User) s.load(User.class, 1);
        System.out.println("log1");
        System.out.println(user.getId());    //使用load访问对象时,获得该对象的id(即主属性),不访问数据库
        System.out.println("log2");
        System.out.println(user.getName());   //当访问非主属性(name)之类的就会访问数据库,执行数据库查询了
         
        t.commit();
        return user;
    }
     
    public static void main(String[] args) {
        User read = load();
        //System.out.println(read.getName());   //对象是从数据库加载的
    }
}

在这里插入图片描述

Hibernate延迟加载

延迟加载又叫lazyload,在one-many many-many的时候都可以使用关系的延迟加载

当Category.hbm.xml中lazy="true"时,表示通过Category获取产品是延迟加载的

package com.test;

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

import com.pojo.Category;
 
public class TestHibernate {
    public static void main(String[] args) {
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
 
        Session s = sf.openSession();
        s.beginTransaction();
        Category c = (Category) s.get(Category.class, 1);          //获取category对象
 
        System.out.println("log1");
        System.out.println(c.getProducts());      //通过category取products
        System.out.println("log1");
 
        s.getTransaction().commit();
        s.close();
        sf.close();
    }
}

执行15行的时候,只会查询Category表的信息,不会查询product_表;
只有在执行18行,通过category取products的时候,才会进行对product_表的查询
但如果没设置延迟加载,则会查询所有的表;

在这里插入图片描述

Hibernate级联

什么是级联?

简单的说,没有配置级联的时候,删除分类,其对应的产品不会被删除。 但是如果配置了恰当的级联,那么删除分类的时候,其对应的产品都会被删除掉。

级联有4种类型:

all:所有操作都执行级联操作;(all 就是 delete+save-update)
none:所有操作都不执行级联操作;
delete:删除时执行级联操作;
save-update:保存和更新时执行级联操作;
级联通常用在one-many和many-to-many上,几乎不用在many-one上

  1. delete 级联
    Category.hbm.xml 加上:

set name=“products” cascade=“delete” lazy="false"

Category.hbm.xml

<?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 package="com.pojo">
    <class name="Category" table="category_">
        <id name="id" column="id">
            <generator class="native">
            </generator>
        </id>
        <property name="name" />
  
        <set name="products" cascade="delete" lazy="false">
            <key column="cid" not-null="false" />
            <one-to-many class="Product" />                          <!--一对多关系-->
        </set>
                  
    </class>
      
</hibernate-mapping>

在一对多代码的基础之上,修改TestHibernate.java为:

package com.how2java.test;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
 
import com.how2java.pojo.Category;
 
public class TestHibernate {
    public static void main(String[] args) {
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
        Session s = sf.openSession();
        s.beginTransaction();
        Category c = (Category) s.get(Category.class, 3);
        s.delete(c);                //删除该分类后,该分类下的所有产品也被删除
        s.getTransaction().commit();
        s.close();
        sf.close();
    }
}
  1. save-update 级联
    为Category.hbm.xml 加上:

set name=“products” cascade=“save-update” lazy="false"

<?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 package="com.pojo">
    <class name="Category" table="category_">
        <id name="id" column="id">
            <generator class="native">
            </generator>
        </id>
        <property name="name" />
  
        <set name="products" cascade="save-update" lazy="false">
            <key column="cid" not-null="false" />
            <one-to-many class="Product" />
        </set>
                  
    </class>
      
</hibernate-mapping>

在一对多代码的基础之上,修改TestHibernate.java为:

package com.test;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
 
import com.how2java.pojo.Category;
import com.how2java.pojo.Product;
 
public class TestHibernate {
    public static void main(String[] args) {
        SessionFactory sf = new Configuration().configure().buildSessionFactory();
        Session s = sf.openSession();
        s.beginTransaction();
        Category c = (Category) s.get(Category.class, 5);
         
        Product p1 = new Product();    //新建3个产品
        p1.setName("product_501");
        Product p2 = new Product();
        p2.setName("product_502");
        Product p3 = new Product();
        p3.setName("product_503");
 
        c.getProducts().add(p1);         //向分类中加产品
        c.getProducts().add(p2);
        c.getProducts().add(p3);
 
        s.getTransaction().commit();
        s.close();
        sf.close();
    }

}

运行代码就会发现,这3个瞬时状态的产品对象虽然没有添加到数据库里(没有用s.save(p1)),但是在事务提交的时候,会把他们3个持久化。 如果没有cascade=“save-update”,就会报错

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值