Hibernate(二)

1 缓存

1.1 什么是缓存?

  • 数据存到数据库里面,数据库本身是文件系统,使用流操作文件效率不是很高。将数据存在内存里面不需要使用流的方式,可以直接读取内存中的数据。把数据收到内存中可以提高读取效率。
  • 提供缓存的目的是为了让数据访问的速度适应CPU的处理速度

1.2 Hibernate的一级缓存

  • hibernate的一级缓存是默认打开的。
  • hibernate的一级缓存的使用范围是session的范围,即从session被实例化到被关闭的过程
  • hibernate的一级缓存中,存储的数据必须是持久态(由session获得的)的数据。
  • hibernate的二级缓存默认不是打开的,并且现在都用redis去代替它,其使用范围为sessionFactory范围

1.3 验证一级缓存的存在

  • 验证方式:两次查询uid = 1的对象,第一次会查数据库,第二次就会从缓存中取
        Students students = session.get(Students.class,3);
        Students students2 = session.get(Students.class,3);

只有第一句会向数据库发送sql语句。

1.4 一级缓存的执行过程

  • 调用Students students = session.get(Students.class,3);后
  • 首先查询一级缓存区,查看是否存在id = 3的这个对象,如果存在则直接返回。
  • 如果不存在,则向数据库发送请求,返回的对象再存入一级缓存中。

1.5 一级缓存特性-持久态自动更新数据库

  • 持久态数据会自动更新数据库而不需要去调用类似session.update()方法。
Students students = session.get(Students.class,3);
students.setName("jacob");
//session.update(students);//不需要调用update也会更新数据库
  • 原理如下图:


    特性执行过程

2 事务标准写法

    @Test
    public void testTX(){
        StandardServiceRegistry standardServiceRegistry = null;
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try {
            standardServiceRegistry = new StandardServiceRegistryBuilder().configure().build();
            sessionFactory = new MetadataSources(standardServiceRegistry).buildMetadata().buildSessionFactory();
            session = sessionFactory.openSession();
            //开启事务
            tx = session.beginTransaction();
            Students students = session.get(Students.class,3);
            students.setGender("女");
            //抛出异常,回滚,性别仍是男
            int a = 1/0;
            System.out.println(a);
            students.setGender("男");
            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

3 三种查询api

  • Query对象
            Query query = session.createQuery("from Students");
            List list = query.list();
            for(Students student:list){
                System.out.println(student);
            }
  • Criteria对象
            Criteria criteria = session.createCriteria(Students.class);
            List list = criteria.list();
            for(Students student:list){
                System.out.println(student);
            }
  • SQLQuery对象
//返回数组类型
            SQLQuery sqlQuery  = session.createSQLQuery("select * from students");
            List list = sqlQuery.list();
            for(Object[] objects:list){
                System.out.println(Arrays.toString(objects));
            }
//返回对象类型
            SQLQuery sqlQuery  = session.createSQLQuery("select * from students");
            sqlQuery.addEntity(Students.class);
            List list = sqlQuery.list();
            for(Students students:list){
                System.out.println(students);
            }

4 一对多操作

4.1 一对多配置

  • 以联系人与客户为例,客户是一,联系人是多。
  1. 创建两个实体类,客户和联系人。
  2. 让两个实体类互相表示。
  3. 创建映射文件,配置一对多关系。(映射文件中,表示所有联系人)
  4. 配置多对一关系。(映射文件中,表示所属客户)。
  5. 将映射文件引入核心配置文件。
  • 接来下是各个步骤对应的代码:
    1/2. 实体类创建并互相表示
import java.util.List;

public class Customer {
    private Integer cid;
    private String custName;
    private String custLevel;
    private String custSource;
    private String custPhone;
    private String custMobile;
    private List list;

    public List getList() {
        return list;
    }

    public void setList(List list) {
        this.list = list;
    }

    public Customer() {
    }

    public Customer(Integer cid, String custName, String custLevel, String custSource, String custPhone, String custMobile, List list) {
        this.cid = cid;
        this.custName = custName;
        this.custLevel = custLevel;
        this.custSource = custSource;
        this.custPhone = custPhone;
        this.custMobile = custMobile;
        this.list = list;
    }

    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }

    public String getCustName() {
        return custName;
    }

    public void setCustName(String custName) {
        this.custName = custName;
    }

    public String getCustLevel() {
        return custLevel;
    }

    public void setCustLevel(String custLevel) {
        this.custLevel = custLevel;
    }

    public String getCustSource() {
        return custSource;
    }

    public void setCustSource(String custSource) {
        this.custSource = custSource;
    }

    public String getCustPhone() {
        return custPhone;
    }

    public void setCustPhone(String custPhone) {
        this.custPhone = custPhone;
    }

    public String getCustMobile() {
        return custMobile;
    }

    public void setCustMobile(String custMobile) {
        this.custMobile = custMobile;
    }
}
public class Contacter {
    private Integer conId;
    private String conName;
    private String conGender;
    private String conPhone;
    private Customer customer;

    public Contacter() {
    }

    public Contacter(Integer conId, String conName, String conGender, String conPhone, Customer customer) {
        this.conId = conId;
        this.conName = conName;
        this.conGender = conGender;
        this.conPhone = conPhone;
        this.customer = customer;
    }

    public Integer getConId() {
        return conId;
    }

    public void setConId(Integer conId) {
        this.conId = conId;
    }

    public String getConName() {
        return conName;
    }

    public void setConName(String conName) {
        this.conName = conName;
    }

    public String getConGender() {
        return conGender;
    }

    public void setConGender(String conGender) {
        this.conGender = conGender;
    }

    public String getConPhone() {
        return conPhone;
    }

    public void setConPhone(String conPhone) {
        this.conPhone = conPhone;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
}
  1. 创建映射文件配置一对多关系




    
        
            
            
        
        
            
        
        
            
        
        
            
        
        
            
        
        
            
        
        
        
            
            
            
            
        
    

  1. 创建多对一关系




    
        
            
            
        
        
            
        
        
            
        
        
            
        
        
    

  1. 导入配置文件
        
        
  1. 编写工具类 + 测试
public class HibernateUtils {
    static StandardServiceRegistry ssregistry = null;
    static SessionFactory sessionFactory = null;
    static {
        ssregistry = new StandardServiceRegistryBuilder().configure().build();
        sessionFactory = new MetadataSources(ssregistry).buildMetadata().buildSessionFactory();
    }
    public static Session getSessionObject(){
        return sessionFactory.getCurrentSession();
    }
    public static SessionFactory getSessionFactory(){
        return sessionFactory;
    }
    public static void main(String []args){

    }
}

运行该类即可发现数据库创建了两张表。

结果

4.2 级联保存

  • 方式一:
public class HibernateOneToManyTest {
    @Test
    public void oneToManyTest(){
        Session session = null;
        SessionFactory sessionFactory = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtils.getSessionFactory();
            session = HibernateUtils.getSessionObject();
            tx = session.beginTransaction();
            Customer customer = new Customer();
            customer.setCustLevel("vip");
            customer.setCustMobile("111");
            customer.setCustName("阿里巴巴");
            customer.setCustSource("网络");
            customer.setCustPhone("222");

            Contacter contacter = new Contacter();
            contacter.setConGender("男");
            contacter.setConName("jacob");
            contacter.setConPhone("333");

            customer.getList().add(contacter);
            contacter.setCustomer(customer);
            session.save(customer);
            session.save(contacter);
            tx.commit();
        }catch (Exception e){
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }
}
  • 方式二:
  1. 首先在映射文件中添加配置cascade="save-update"
        
        
            
            
            
            
        
  1. 代码:
            Customer customer = new Customer();
            customer.setCustLevel("vip");
            customer.setCustMobile("111");
            customer.setCustName("因特尔");
            customer.setCustSource("网络");
            customer.setCustPhone("222");

            Contacter contacter = new Contacter();
            contacter.setConGender("男");
            contacter.setConName("rose");
            contacter.setConPhone("333");

            customer.getList().add(contacter);
            session.save(customer);

4.3 级联删除

  • 有外键关联时的删除做法。
    直接删除一个customer是会报错的,因为有外键对其关联。


    删除报错
  • 做法步骤应如下:
  1. 删除从表的对应数据
  2. 删除主表对应数据
  • 级联删除的步骤如下:
  1. 在客户映射文件进行配置
        
        
            
            
            
            
        
            Customer customer = session.get(Customer.class,2);
            session.delete(customer);

4.4 更改联系人

            Customer customer = session.get(Customer.class,1);
            Contacter contacter = session.get(Contacter.class,11);
            customer.getList().add(contacter);
            contacter.setCustomer(customer);
  • 问题在于会进行两次外键设置,使得运行负担较大。
  • 解决方法 inverse="true"
        
            
            
            
            
        

你可能感兴趣的:(Hibernate(二))