Session概述:
-Session接口是Hibernate向应用程序各供的操作数据库的最主要的接口,它提供了基本的保存、更新、删除和加载Java对象的方法。
-Session具有一个缓存,位于缓存中的对象称为持久化对象,它和数据库中相关记录对应。Session能够在某些时间点,按照缓存中对象的变化来执行相关的SQL语句,来同步更新数据库,这一过程被称为刷新缓存(flush)
-站在持久化的角度,Hibernate把对象分为4种状态:持久化状态,临时状态,游离状态,删除状态。Session的特定方法能使对象从一个状态转换到另一个状态
Session缓存:
什么是缓存?
即使就是一块内存空间,将数据源(数据库或者文件)中的数据存放到缓存中。再次获取的时候,直接从缓存中获取。可以提升程序的性能!
Hibernate框架提供了两种缓存:
一级缓存---自带的不可卸载的,一级缓存的声明周期与Session一致。一级缓存称为Session级别的缓存。
二级缓存---默认没有开启,需要手动配置才可以使用的。二级缓存可以在多个Session中共享数据,二级缓存称为SessionFactory级别的缓存.
Session对象的缓存概述:
-在Session接口的实现中包含一系列的java集合,这些Java集合构成了Session缓存,只要Session实例没有结束生命周期,且没有清理缓存,则存放在它缓存中的对象也
不会结束生命周期.
-Session缓存可减少Hibernate应用程序访问数据库的频率。
证明:只向数据库发送了一条SQL,而查询了2次,并且是同一个对象。
事务:
什么是事务?
事务就是逻辑上的一组操作,组成事务的各个执行单元,操作要么全部成功,要么全部失败。
例子:转账的例子;A给B转钱,扣钱,加钱。两个操作组成了一个事务!
事务对的特性:
原子性----事务不可分割。
一致性----事务执行的前后数据的完整性保持一致。
隔离性----一个事务执行的过程中,不应该受到其他的事务的干扰
持久性----一旦事务提交,数据就永久保存到数据库中。
如果不考虑 数据库的隔离级别:对于同时运行的多个事物,当这些事物访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:
-脏读:对于两个事物T1,T2,T1读取了已经被T2更新但还没有被提交的字段之后,若T2回滚,T1读取的内容就是临时且无效的。
-不可重复读:对于两个事物T1,T2, T1读取了一个字段,然后T2更新了该字段之后,T1再次读取同一个字段,值就不同了(就是读取了T2 update操作之前之后的操作)
-幻读:对于两个事物T1,T2 ,T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行之后,如果T1再次读取同一个表,就会多出几行。(就是读取了T2 insert操作之前之后的操作)
设置数据库事务的隔离性:数据库系统必须具有隔离并发运行各个事务的能力,使他们不会相互影响,避免各种并发问题。(来解决上面的问题)
一个事务与其他事务隔离的成都称为隔离级别,数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱
-未提交读:以上的读的问题都有可能发生
-已提交读:避免脏读,但是不可重复读,虚读都有可能发生
-可重复读:避免脏读,不可重复读,但是虚读是可能发生的
-串行化:以上读的情况都可以避免
如果想在Hibernate的框架中来设置隔离级别,需要在hibernate.cfg.xml的配置文件中通过标签来配置
通过:hibernate.connection.isolation=4(一般用4)来配置
1-Read uncommitted isolation
2-Read committed isolation
4-Repeatable read isolation
8-Serializable isolation
参考博客:https://www.cnblogs.com/fjdingsd/p/5273008.html
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 ????????"-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 ????????"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 ????<session-factory> 7 ????????<!-- 配置连接数据库的基本信息 --> 8 ????????<property name="connection.username">root</property> 9 ????????<property name="connection.password">root</property>10 ????????<property name="connection.driver_class">com.mysql.jdbc.Driver</property>11 ????????<property name="connection.url">jdbc:mysql:///hibernate5</property>12 13 ????????<!-- 配置hibernate的基本信息 -->14 ????????<!-- hibernate所使用的数据库方言 -->15 ????????<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>16 ????????17 ????????<!-- 执行操作时是否在控制台打印SQL -->18 ????????<property name="show_sql">true</property> ???????19 ????????<!-- 是否对SQL进行格式化 (分行显示)-->20 ????????<property name="format_sql">true</property> ???????21 ????????<!-- 指定自动生成数据表的策略 -->22 ????????<property name="hbm2ddl.auto">update</property> ??????23 ????????24 ????????<!-- 设置Hibernate的事务隔离级别 -->25 ????????<property name="connection.isolation">2</property>26 ????????27 ????????<!-- 指定关联的.hbm.xml文件 -->28 ????????<mapping resource="com/tzy/hibernate/News.hbm.xml"/>29 ????????30 ????</session-factory>31 </hibernate-configuration>
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-11-19 16:22:35 by Hibernate Tools 3.4.0.CR1 --> 5 <hibernate-mapping> 6 ????<class name="com.tzy.hibernate.News" table="NEWS"> 7 ????????<id name="id" type="java.lang.Integer"> 8 ????????????<column name="ID" /> 9 ????????????<!-- 指定逐渐生成的方式,native:使用数据库本地方式 -->10 ????????????<generator class="native" />11 ????????</id>12 ????????13 ????????<property name="title" type="java.lang.String">14 ????????????<column name="TITLE" />15 ????????</property>16 ????????17 ????????<property name="author" type="java.lang.String">18 ????????????<column name="AUTHOR" />19 ????????</property>20 ????????21 ????????<property name="date" type="java.util.Date">22 ????????????<column name="DATE" />23 ????????</property>24 ????????25 ????</class>26 </hibernate-mapping>
1 package com.tzy.hibernate; 2 ?3 import java.util.Date; 4 ?5 public class News { 6 private Integer id; 7 private String title; 8 private String author; 9 private Date date;10 public Integer getId() {11 ????return id;12 }13 public void setId(Integer id) {14 ????this.id = id;15 }16 public String getTitle() {17 ????return title;18 }19 public void setTitle(String title) {20 ????this.title = title;21 }22 public String getAuthor() {23 ????return author;24 }25 public void setAuthor(String author) {26 ????this.author = author;27 }28 public Date getDate() {29 ????return date;30 }31 public void setDate(Date date) {32 ????this.date = date;33 }34 35 public News(String title, String author, Date date) {36 ????super();37 ????this.title = title;38 ????this.author = author;39 ????this.date = date;40 }41 public News() {42 ????super();43 }44 @Override45 public String toString() {46 ????return "News [id=" + id + ", title=" + title + ", author=" + author + ", date=" + date + "]";47 }48 49 }
1 package com.tzy.hibernate; 2 ?3 import java.util.Date; 4 ?5 import org.hibernate.Session; 6 import org.hibernate.SessionFactory; 7 import org.hibernate.Transaction; 8 import org.hibernate.boot.MetadataSources; 9 import org.hibernate.boot.registry.StandardServiceRegistry;10 import org.hibernate.boot.registry.StandardServiceRegistryBuilder;11 import org.junit.Test;12 13 public class HibernateTest {14 ????15 ????@Test16 ????public void test() {17 ????????//1.创建一个SessionFactory对象18 ????????SessionFactory sessionFactory = null;19 ????????20 ????????//hibernate4获取sessionFactory办法21 ????????//1).创建Configuration对象:对应hibernate的基本配置信息和关系映射信息22 ????????//Configuration configuration = new Configuration().configure();23 ????????//4.0之前这样创建24 ????????//sessionFactory = configuration.buildSessionFactory();25 ????????//2).创建一个ServiceRegistry对象:hibernate 4.x新添加的对象26 ????????//hibernate的任何配置和服务都需要在该对象中注册后才能有效。27 ????????//ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())28 ????????// ???????????????????????????????????????????????????????????????.buildServiceRegistry();29 ????????//3).30 ????????//sessionFactory = configuration.buildSessionFactory(serviceRegistry);31 ????????32 ????????//4).33 ????????//hibernate5获取sessionFactory办法34 ????????//创建StandardServiceRegistry对象(标准服务注册)35 ????????StandardServiceRegistry standardServiceRegistry = new StandardServiceRegistryBuilder().configure().build();36 ????????37 ????????sessionFactory = new MetadataSources(standardServiceRegistry).buildMetadata().buildSessionFactory();38 ????????//2.创建一个Session对象39 ????????Session session = sessionFactory.openSession();40 ????????41 ????????//3.开启事物42 ????????Transaction transaction = session.beginTransaction();43 ????????44 ????????//4.执行保存操作45 ????????News news = new News("Java", "Tzy", new Date());46 ????????session.save(news);47 ????????48 ????????News news2 = session.get(News.class, 1);49 ????????System.out.println(news2);50 ????????//5.提交事物51 ????????transaction.commit();52 ????????53 ????????//6.关闭Session54 ????????session.close();55 ????????56 ????????//7.关闭SessionFactory对象57 ????????sessionFactory.close();58 ????}59 60 }
绑定本地Session
1、hibetnate是通过把session绑定到线程中,来解决事务问题的(通过ThreadLocal)
2、现在的Hibernate框架中,使用session对象开启事务,所以需要来传递session对象,框架提供了ThreadLocal的方式
需要在hibernate.cdg.xml的配置文件中提供配置<property name="hibernate.current_session_context_class">thread</property>
修改session的获取方式为 SessionFactory.getCurrentSession();
3、这样在Transaction(事务)提交的时候可以通过抛异常的方式执行transaction.rollback();方法,回滚事务,
注意:使用这种session的事务执行提交操作过后,hibernate会帮助我们在线程执行完毕将session关闭。我们就不需要在finally里面去关闭session了
持久化对象的状态
-站在持久化的角度,Hibernate把对象分为4种状态:持久化状态,临时状态,删除状态。Session的特定方法能使对象从一个状态转换到另一个状态
临时对象(Transient)
- 在使用代理主键的情况下,OID通常为null
- 不处于Session的缓存中
- 在数据库中没有对应的记录
持久化对象(也叫“托管”)(Persist)
- OID不为null
- 位于Session缓存中
- 若在数据库中已经有和其对应的记录,持久化对象和数据库中的相关记录对应
- Session在flush缓存时,会根据持久化对象的属性变化,来同步更新数据库
- 在同一个Session实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象
删除对象(Removed)
- 在数据库中没有和其OID对应的记录
- 不再处于Session缓存中
- 一般情况下,应用程序不该在使用被删除的对象
游离对象(也叫“脱管”)(Detached)
- OID不为null
- 不再处于Session缓存中
- 一般情况下,游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录
Hibernate框架的查询方式
Criteria查询接口(做条件查询非常合适)
1、QBC:Query By Criteria -----按条件经行查询
2、QBC:查询方式的使用
---先创建查询接口 Criteria c = session.createCriteria(User.class);
---设置查询的条件 c.add(Restrictions.gt("age",10)); 查询年龄大于10的
模糊查询用c.like(Restrictions.gt("name","%熊%"));
多条件查询(and) c.like(Restrictions.gt("name","%熊%")); c.add(Restrictions.gt("age",10)); 查询出来的就是名字有熊的年龄大于10的
多条件查询(ro) c.add(Restrictions.or(Restrictions.gt("name","%熊%"),Restrictions.gt("age",10)));
在什么之间查询 c.like(Restrictions.between("age",10,30)); 查询年龄10-30之间的
----查询数据 List<User> list = c.list();
----分页 c.setFirstResult(2); //第三条数据开始 c.setMaxResult(2); //每页数据2条
一对多,多对一:
新建一个客户和两个联系人
Customer c = new Customer();
c.setCust_name("马妹妹");
LinkMan m1 = new LinkMan();
m1.setLkm_name("强哥");
LinkMan m2 = new LinkMan();
m1.setLkm_name("小宋");
双向关联
客户关联联系人(获取联系人引用的set集合添加元素)
c.getLinkmans().add(m1);
c.getLinkmans().add(m1);
联系人关联客户(设置客户引用的元素)
m1.setCustomer(c);
m2.setCustomer(c);
使用session保存
session.save(c);
session.save(m1);
session.save(m2);
提交事务
tr.commit();
单项关联
客户关联联系人(获取联系人引用的set集合添加元素)
c.getLinkmans().add(m1);
c.getLinkmans().add(m1);
使用session保存
session.save(c);
提交事务
tr.commit();
注意:由于m1,m2创建出来为临时状态(顺时态),没有OID,不能保存到数据库,故需要配置在Customer.hbm.xml文件的set标签中添加
cascade="save-update" 属性,使customer在添加linkMans引用的时候让m1,m2从顺时态变成持久态
还可以通过session保存m1,m2让hibernate访问数据库的频率降低
联系人关联客户(设置客户引用的元素)
m1.setCustomer(c);
m2.setCustomer(c);
使用session保存
session.save(m1);
session.save(m2);
提交事务
tr.commit();
那么需要在LinkMans.hbm.xml文件的<many-to-one>标签中设置cascade="save-update" 属性,使linkMans在添加customer引用的时候让c从顺时态变成持久态
************在开发的角度(一般采用在多对一的多方设置该属性)*************
相应的在做级联删除的时候就添加cascade="delete" 属性(但是要配置在一方,不然如果配置在多方,多方会有数据残留,故开发配在单方)
cascade取值:
none-----不使用级联 save-update----级联保存或者更新 delete----级联删除 delete-orphan----孤儿删除(只能应用在一对多关系)
all---除了delete-orphan的所有情况(包含save-update delete) all-delete-orphan-----包含了delete-orphan的所有情况(包含seve-update delete delete-orphan)
孤儿删除解释:在一对多的方腊中,可以将一的一方认为是父方,将多的一方认为是子方,孤儿删除就是在解除父子关系的时候,将子房记录直接删除。
那么 如果我们只想删除多方的一条数据,就要使用到孤儿删除,例子:在Customer.hbm.xml文件中的set标签里设置cascade="delete-orphan" 属性
获取客户
Customer c = session.get(Customer.class,1);
获取2号联系人
LinkMan m2 = session.get(LinkMan.class,2);
然后解除关系(获取客户引用的联系人集合,集合操作remove掉联系人2,然后利用hibernate快照机制就可以使联系人2被删除)
c.getLinkMans().remove(m2);
**inverse属性可以用来维护外键,true的时候为放弃,flase时候为不放弃,设置在一方***
多对多:
User u1 = new User("霆锋");
User u2 = new User("柏芝");
Role r1 = new Role("演员");
Role r2 = new Role("歌手");
双向级联
//霆锋演员+演员
u1.getRoles().add(r1);
u1.getRoles().add(r2);
r1.getUsers().add(u1);
r2.getUsers().add(u2);
//柏芝演员
u2.getRoles().add(r1);
r1.getUsers().add(u2);
//session保存
session.save(u1);
session.save(u2);
session.save(r1);
session.save(r2);
运行报错,原因是因为2个多方都进行了外键的维护,所以要让一方放弃外键的维护,在set标签中加入inverse=“true”属性
单向级联
配置单项级联属性cascade="save-update"
//霆锋演员+演员
u1.getRoles().add(r1);
u1.getRoles().add(r2);
//柏芝演员
u2.getRoles().add(r1);
//session保存
session.save(u1);
session.save(u2);
Hibernate 内容记录
原文地址:http://www.cnblogs.com/ttzzyy/p/7874909.html