Hibernate框架的入门(二)

hibernate学习笔记day2

1.相关基础概念
  • 持久化:将内存的一个对象持久化到数据库中的过程,hibernate框架就是用来进行持久化的框架

  • 持久化类: 一个Java对象与数据库的表建立映射关系,这个类在hibernate中就可以称为持久化类。

    持久化类=Java类+映射文件

2.持久化类的编写规则
  • 对持久化类提供一个无参数的构造方法–>hibernate底层需要使用反射生成实例。
  • 属性需要私有,对私有属性提供public的get和set方法–>hibernate中获取和设置对象的值
  • 对持久化类提供唯一的标识OID与数据库主键对应–>Java中通过对象的地址区分是否是同一个对象,在数据库中通过主键确定是否是同一个记录,在hibernate中通过持久化类的OID的属性确定是否是同一个对象。
  • 持久化类中的属性尽量使用包装类的类型–>因为基本数据类型默认为0,那么0就会产生很多歧义。包装类类型的默认值是null。
  • 持久化类不要使用final进行修饰–>延迟加载本身是hibernate一个优化的手段,返回的是一个代理对象(javassit可以对没有实现借口的类产生代理–使用非常底层的字节码增强技术,继承这个类进行代理。如果不能继承,就不能产生代理对象,延迟加载也久失效。load()和get()方法就变成一样效果了。
3. 主键生成策略
  • 1.主键的分类
    • 1.自然主键

      主键本身就是数据库表中的一个字段(实体中的一个具体属性)
      就是使用实际表中的主键,就是自然主键

    • 2.代理主键

      主键本身不是表中的必须的一个字段(不是实体中某个具体的属性)
      使用了一个与表完全不相关的字段就叫做代理主键

    • 3.在实际开发中,尽量使用代理主键

      如果自然主键参与到业务逻辑中,后期有可能需要修改源代码
      好的程序设计满足OCP原则,对程序是open可扩展的,对修改源代码是close的。

  • 2.主键生成策略
    在实际开发中一般不允许用户手动设置主键,一般将主键交给数据库,手动编写程序进行设置,在hibernate中为了减少程序编写,提供了很多主键的生成策略。
    • increment : hibernate中提供的自动增长机制,适用于short、int、long类型的主键,在单线程程序中使用。

      首先发送一条语句,select max(id) from 表,然后让id+1作为下一条记录的主键。

    • identity : 适用于short、int、long类型的主键,使用的是数据库底层的自动增长机制,适用于有自动增长机制的数据库(mysql、mssql),但oracle没有自动增长。

    • sequence : 使用与short、int、 long类型的主键,采用序列的方法(oracle支持序列)。但mysql就不能使用sequence。

    • uuid : 适用于字符串类型的主键,使用hibernate中的随机方式生成字符串主键。

    • native : 本地策略,在identity和sequence之间进行自动切换。

    • assigned : hibernate放弃外键的管理,需要通过手动编写程序或用户自己设置。

    • foreign : 外部的,一对一的一种关联映射的情况下使用。

4.持久化类的三种状态

  • 1.持久化类的三种状态

    • 1.瞬时态

      瞬时态也称为临时态或者自由态,瞬时态的实例是由new命令创建,开辟内存空间的对象,不存在持久化类标识OID(相当于主键),尚未与hibernate Session关联,在数据库中也没有记录。

    • 2.持久态

    持久态的对象有标识OID,加入到了Session对象中,与Session关联并且被Session管理,在数据库中有对应的记录,持久态对象是在事务还未提交前变成持久态的。

    • 3.脱管态

    也称离线态或者游离态,当某个持久化状态的实例与session的关联状态关闭时就变成脱管态,脱管态对象存在对应的持久化标识OID,并且与数据库数据存在关联,只是失去了与当前Session的关联,托管状态对象发生改变时Hibernate不能检测到。

  • 2.区分对象的三种状态

public void demo1() {
	Session session=HibernateUtils.openSession();
	Transaction tx=session.beginTransaction();
	//瞬时对象,没有唯一的OID,没有被session管理
	Customer customer=new Customer();
	customer.setCust_name("李佳");
	
	//被session管理,变成持久态对象,有唯一标识OID
	Serializable id=session.save(customer);
	
	tx.commit();
	//关闭session,这个对象变成脱管态对象,有唯一的OID没有被session管理
	session.close();
}
  • 3.三种状态的转换
    • 瞬时对象
      1.获得
      Customer customer=new Customer();
      2.状态转换
      瞬时————>持久
      save(Object obj)、 saveOrUpdate(Object obj);
      瞬时–>托管
      customer.setCust_id(1);

    • 持久态对象
      1.获得
      get(),load(),find(),iterate()
      Customer customer=session.get(Customer.class,1);
      2.状态转换
      持久态–>瞬时态
      delete()
      持久态–>脱管态
      close(),clear(),evict(Object obj)

    • 脱管态对象
      1.获得
      Customer customer=new Customer();
      customer.setCust_id(1);
      2.状态转换
      脱管态–>持久态
      update(),saveOrUpdate()
      脱管态–>瞬时态
      customer.setCust_id(null);

5. 缓存的概述

  • 1.什么是缓存?

缓存是一种优化的方式,将数据存入到内存中,使用的时候直接从缓存中获取,不用通过存储源。

  • 2.Hibernate的一级缓存
    Hibernate框架中提供了优化手段,缓存,抓取策略,Hibernate中提供了二种缓存机制:一级缓存和二级缓存。Hibernate的一级缓存是session级别的缓存,一级缓存的生命周期与session一致(一级缓存是由session中的一系列的Java集合构成),一级缓存是自带的不可卸载的(Hibernate的二级缓存是SessionFactory级别的缓存,需要配置的缓存)。
  • 3.证明一级缓存的存在
	@Test
	public void demo1() {

		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();

  /* 
    Customer customer1 = session.get(Customer.class, 1);
		System.out.println(customer1);

		Customer customer2 = session.get(Customer.class, 1);
		System.out.println(customer2);

		System.out.println(customer1 == customer2);
   */
		
		Customer customer=new Customer();
		customer.setCust_name("老满天");
		Serializable id= session.save(customer);
		//不发送SQL语句
		Customer customer2=session.get(Customer.class, id);
		System.out.println(customer2);
		
		tx.commit();
		session.close();
	}

6.事务的回顾

  • 1.什么是事务?
    事务是指逻辑上的一组操作,组成这组操作的各个逻辑单元要么全部成功,要么全部失败。

  • 2.事务的特性

    • 1.原子性 : 代表事务不可分割
    • 2.一致性 : 代表事务执行的前后,数据的完整性保持一致
    • 3.隔离性 : 代表一个事务执行的过程中,不应该收到其他事务的干扰。
    • 4.持久性 : 代表事务执行完成后,数据持久到数据库中。
  • 3.如果事务不考虑隔离性,引发安全性问题

    • 1.读问题
      ** 脏读 :一个事务读到另一个事务未提交的数据
      ** 不可重复读 :一个事务读到另一个事务已经提交的update数据,导致在前一个事务多次查询结果不一致。
      ** 幻读(虚读):一个事务读到另一个事务已经提交的insert数据,导致在前一个事务多次查询结果不一致。
    • 2.写问题
      ** 引发两类丢失更新
  • 4.读问题的解决

    • 设置事务的隔离级别
read uncommitted :以上读问题都可能产生
read committed :解决脏读,但可能产生不可重复读和幻读
repeatable read :解决脏读和不可重复读,但可能产生幻读
serializable  : 解决所有读问题
  • 5.在hibernate配置文件中设置事务的隔离级别
<!--设置事务的隔离级别-->
<property name="hibernate.connection.isolation">4</property>
  • 6.设置线程绑定Session
public class HibernateUtils {
   //抽取工具类
	public static final Configuration cfg;
	public static final SessionFactory sf;

	static {
		cfg = new Configuration().configure();
		sf = cfg.buildSessionFactory();
	}

	public static Session openSession() {
		return sf.openSession();
	}
	public static Session getCurrentSession() {
		return sf.getCurrentSession();
	}
//在配置文件中配置
<property name="hibernate.current_session_context_class">thread</property>
@Test
public void demo1() {
	Session session=HibernateUtils.getCurrentSession();
	Transaction tx=session.beginTransaction();
	Customer customer =new Customer();
	customer.setCust_name("lijia");
	session.save(customer);
	tx.commit();
}

7. Hibernate中其他的API

  • HQL
    • Hibernate查询语言(HQL)与SQL(结构化查询语言)相同,但不依赖于数据库表。 我们在HQL中使用类名,而不是表名。 所以是数据库独立的查询语言。
  • HQL的优点
    • 数据库独立
    • 支持多态查询
查询接口 Query对象
public int executeUpdate()  : 用于执行更新或删除查询。
public List list()  : 将关系的结果作为列表返回。
public Query setFirstResult(int rowno)  : 指定从哪里检索记录的行号。
public Query setMaxResult(int rowno)  : 指定从关系(表)中检索记录的行号。
public Query setParameter(int position, Object value)将该值设置为JDBC样式查询参数。
public Query setParameter(String name, Object value)将该值设置为命名查询参数。
  • 查询实例
@Test
	public void demo1() {
		Session session=HibernateUtils.getCurrentSession();
		Transaction tx=session.beginTransaction();
		//简单查询
		//String hql="from Customer";
		
		//条件查询
		String hql="from Customer where cust_name like ?";
		//设置条件
		//query.setParameter(0,"王%");
		//通过session获得Query接口
		Query query=session.createQuery(hql);
		
		//分页查询
		query.setFirstResult(0);//第一个参数角标是0
		query.setMaxResults(3);
		
		List<Customer> list=query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tx.commit();
	}
  • 总结
    1. 获取所有表中记录
1. 获取所有表中记录
Query query=session.createQuery("from tableName"); 
List list=query.list();

2.删除实例
Query query=session.createQuery("delete from tableName where id=100");   
query.executeUpdate();

3. 获取分页记录
Query query=session.createQuery("from tableName");  
query.setFirstResult(5);  
query.setMaxResult(10);  
List list=query.list();
查询接口Criteria对象
    1. Criteria接口
      Criteria接口提供了许多方法来指定条件。 可以通过调用Session接口的createCriteria()方法获得Criteria对象。
    1. Criteria接口常用的方法
 * public Criteria add(Criterion c)  : 用于添加限制(条件)。
 * public Criteria addOrder(Order o)  : 指定排序顺序。
 * public Criteria setFirstResult(int firstResult)  : 指定要检索的第一个记录数。
 * public Criteria setMaxResult(int totalResult)  : 指定要检索的记录总数。
 * public List list()  : 返回包含对象的列表。
 * public Criteria setProjection(Projection projection)  : 指定投影。

  • 通过session接口的createCriteria()方法获得Criteria的对象
Criteria criteria=session.createCriteria(Customer.class);
		List<Customer> list=criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
  • 获取所有记录的HCQL示例
Criteria criteria=session.createCriteria(Customer.class);
List list=criteria.list();
  • HCQL获得第10到20个记录的例子
Criteria c =session.createCriteria(类名.class);  
c.setFirstResult(10);  
c.setMaxResult(20);  
List list=c.list();
  • HCQL获取薪资大于10000的记录示例
Criteria c =session.createCriteria(类名.class);  
c.add(Restrictions.gt("salary",10000));
List list=c.list();
  • 以薪酬(Salary)为基础升序排序记录的HCQL示例
Criteria c =session.createCriteria(类名.class);  
c.addOrder(Order.asc("salary"));  
List list=c.list();
  • HCQL及投影
Criteria  c =session.createCriteria(Emp.class);  
c.setProjection(Projections.property("name"));  
List list=c.list();
Restrictions类
  • Restrictions类提供可用作标准的方法。 常用的Restrictions类方法如下:
public static SimpleExpression lt(String propertyName,Object value) 
-->将给定属性的约束设置为小于约束。

public static SimpleExpression le(String propertyName,Object value)
 -->设置给定属性的小于或等于约束。

public static SimpleExpression gt(String propertyName,Object value)
 -->设置给定属性的大于约束。

public static SimpleExpression ge(String propertyName,Object value) 
-->设置给定属性的大于或等于约束。

public static SimpleExpression ne(String propertyName,Object value) 
-->对给定的属性设置不相于约束。

public static SimpleExpression eq(String propertyName,Object value) 
-->设置约束与给定属性相等。

public static Criterion between(String propertyName, Object low, Object high) 
-->设置约束之间范围。

public static SimpleExpression like(String propertyName, Object value) 
-->将类似的约束设置为给定的属性。
Order类
  • Order类代表排序顺序。常用的 Restrictions 类方法如下:
public static Order asc(String propertyName) 适用于给定属性的基础上,按升序排列。

public static Order desc(String propertyName) 适用于给定属性的基础上,按降序排列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值