hibernate的主键生成策略&一级缓存&事务管理学习笔记

持久化

持久化:将内存中的一个对象持久化到数据库的过程。Hibernate框架就是用来持久化的框架。

持久化类:一个java对象与数据表建立了映射关系,那么这个类在Hibernate中称为持久化类。   持久化类= java类  +   映射文件

持久化类的编写规则

1.提供无参构造                                                                    :Hibernate底层使用反射机制

2.私有属性提供公共的set/get方法                                       :Hibernate中获取、设置对象的值

3.对持久化类提供一个唯一标识属性OID与数据库主键对应:java中通过地址区分是否同一个对象,数据库通过主键确定是否同记录

4.持久化类中的属性尽量使用包装类型                                :包装类型默认值为null;基本类型为0,有起义。

5.持久化类尽量不要用final修饰                      :Hibernate使用延迟加载优化,返回的是代理对象,需要继承。(否则load变成get)

Hibernate的主键生成策略

开发中尽量使用代理主键,这样可以在主键发生变化的时候不用修改源代码,也满足OCP原则。

Hibernate在实际开发中不允许用户手动设置主键,一般将主键交给数据库或手动编写程序进行设置。在hibernate中为了减少程序编写,提供了很多的主键生成策略,下面是重点:

increment    hibernate中提供的自动增长机制,适用于short、int、long类型的主键。仅单线程程序中使用。

           原理:首先发送一条语句:select MAX(id) from 表;然后将id+1作为下一条记录的主键。

identity        使用数据库底层的自动增长机制,适用于short、long、int。适用于有自动增长机制的数据库(MySQL、MSSQL)。                 注意:Oracle是没有自动增长的。

 sequence      采用序列机制,适用于short、int、long。适用于序列机制的数据库(Oracle)

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

native     本地策略。可以在identity和sequence间进行自动切换。 

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

foreign      外部的。会在一对一的关联映射下使用。 

 持久化类的三种状态

瞬时态(transient)

对象没有唯一表示OID,还没有被session管理。

持久态(persistent)

对象有唯一标识OID,被session管理。

                 持久化类的持久态对象可以自动更新数据库。

脱管态(detached)

有唯一表示OID,没有被session管理。

	@Test
	public void test1(){
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		Customer  customer = new Customer();
		customer.setCust_name("二蛋");  //瞬时态对象:没有OID,没有被session管理
		
		Serializable id = session.save(customer);//持久态对象:有OID,被session管理
		
		transaction.commit();
		session.close();
		
		System.out.println("客户名称"+customer.getCust_name());//托管态对象:有OID,没被session管理
	}

自动更新到数据库了:

持久化类三种状态的转换

持久态自动保存到数据库中

	@Test//持久态对象自动更新数据库
	public void test2(){
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		Customer customer = session.get(Customer.class, 1l);
		customer.setCust_name("gg");
		//不用保存到脱管,可以自动更新到数据库
//		session.save(customer);
		
		transaction.commit();
		session.close();
	}

那么,持久态是怎么自动保存数据到数据库中的呢——引出hibernate的一级缓存。

 

Hibernate的一级缓存

缓存是一种优化方式,可以将想用的数据保存到内存中,不用去存储源中 。

hibernate提供两个级别的缓存:

一级缓存

session级别的缓存:生命周期与session一致(一级缓存是由Session中的一系列java集合构成的)。一级缓存是hibernate自带的不可卸载。

一级缓存内部结构

一级缓存中的特殊区域:快照区。将一级缓存进行快照,提交的数据和快照区一样不更新数据库,不一致时更新到数据库。

注:close()和clear()和evict(Object obj)可以清除缓存。

二级缓存

默认不开启,需要配置,一般用redis替代二级缓存。是SessionFactory级别的缓存。

Hibernate的事务管理

事务复习链接

在hibernate.cfg.xml中设置事务的隔离级别:

        <!-- 设置事务隔离级别 -->
		<property name="hibernate.connection.isolation">4</property>

隔离级别参见事务部分文章。

 

 往工具类中添加获取当前session的方法:

	/**
	 * 
	 * 这个方法默认不能用,需要配置
	 * <property name="hibernate.current_session_context_class">thread</property>
	 * 可以不需要close();线程结束会自动销毁session
	 * @return
	 */
	public static Session getCurrentSession(){
		return sf.getCurrentSession();
	

绑定session本地线程:

		<!-- 配置session绑定本地线程 -->
		<property name="hibernate.current_session_context_class">thread</property>
/**
 * 测试当前线程绑定的session
 * @author malaganguo
 */
public class HibernateDemo3 {
	@Test
	public void demo1(){
		Session session = HibernateUtils.getCurrentSession();//保证同一个session
		Transaction transaction = session.beginTransaction();
		
		Customer customer = new Customer();
		customer.setCust_name("快乐风男");
		session.save(customer);
		
		transaction.commit();
		//注意:getcurrentSession()方法会自动关闭线程,如果这里再写session.close()会报错。
	}
}

Hibernate的其他API

Query接口

用于接收HQL,查询多个对象。

	@Test
	public void test1(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		//简单查询
		String hql = "from Customer";
		//条件查询
		hql = "from Customer where cust_name like ?";
		
		Query query = session.createQuery(hql);
		//设置条件
		query.setParameter(0, "%");//模糊查询的条件
		//设置分页
		query.setFirstResult(0);//相当于LIMIT的第一个参数,不过这里是从0开始的
		query.setMaxResults(3);//每页显示多少条记录
		
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		
		transaction.commit();
	}

Criteria

	/**
	 * Criteria
	 */
	@Test
	public void test2(){
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
/*		//通过session创建Criteria对象
		Criteria criteria = session.createCriteria(Customer.class);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}*/
		
/*		//criteria模糊查询
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.add(Restrictions.like("cust_name", "男", MatchMode.END));
		//criteria.add(Restrictions.like("cust_name", "%男"));//两种模糊查询方式
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}*/
		//criteria分页查询
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.setFirstResult(0);
		criteria.setMaxResults(3);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		
		transaction.commit();
	}

SQLQuery

Query和Criteria一般都可以搞定,但是遇到复杂的SQL操作,比如表关联等,则需要用到SQLQuery对象。

查询的代码:

		//SQLQuery查询:创建查询时写sql语句就行了
		SQLQuery query = session.createSQLQuery("select * from cst_customer");
		List<Object[]> list2 = query.list();
		for (Object[] objects : list2) {
			System.out.println(Arrays.toString(objects));
		}

SQL查询同样支持分页查询的方法调用和模糊查询的方法调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值