hibernate 执行流程
=================
读取Hibernate 的配置信息-〉创建SessionFactory
1)创建Configuration类的实例。
它的构造方法:将配置信息(Hibernate config.xml)读入到内存。
一个Configuration 实例代表Hibernate 所有Java类到Sql数据库映射的集合。
2)创建SessionFactory实例
把Configuration 对象中的所有配置信息拷贝到SessionFactory的缓存中。
SessionFactory的实例代表一个数据库存储源,创建后不再与Configuration 对象关联。
缓存(cache):指Java对象的属性(通常是一些集合类型的属性--占用内存空间。
SessionFactory的缓存中:Hibernate 配置信息。O\R映射元数据。
3)调用SessionFactory创建Session的方法
Session s=sessionFactory.openSession();
4)通过Session 接口提供的各种方法来操纵数据库访问
JPA(Java Persistence API)
============================
JPA通过注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
注解
@Entity ,注册在类头上,将一个类声明为一个实体bean(即一个持久化POJO类) 。
@Table ,注册在类头上,注解声明了该实体bean映射指定的表(table)。
@Id用来注册主属性,
@GeneratedValue用来注册主属性的生成策略,
@Column用来注册属性,
@Version用来注册乐观锁,
@Transient用来注册不是属性。
以上的@Id、@GeneratedValue、 @Column 、 @Version,可以用来注册属性,既可以写在Java类的属性上,也可以注册在属性对应的getter上。
@Transient注册在多余的属性或多余的getter上,但是必须与以上的@Column等对应。 @Column 标识属性对应的字段,示例:@Column(name=“userName")
@Column的说明:
@Column(
name="columnName"; (1)
boolean unique() default false; (2)
boolean nullable() default true; (3)
boolean insertable() default true; (4)
boolean updatable() default true; (5)
String columnDefinition() default ""; (6)
String table() default ""; (7)
int length() default 255; (8)
int precision() default 0; // decimal precision (9)
int scale() default 0; // decimal scale (10)
(1) name 可选,列名(默认值是属性名)
(2) unique 可选,是否在该列上设置唯一约束(默认值false)
(3) nullable 可选,是否设置该列的值可以为空(默认值false)
(4) insertable 可选,该列是否作为生成的insert语句中的一个列(默认值true)
(5) updatable 可选,该列是否作为生成的update语句中的一个列(默认值true)
(6) columnDefinition 可选: 为这个特定列覆盖SQL DDL片段 (这可能导致无法在不同数据库间移植)
(7) table 可选,定义对应的表(默认为主表)
(8) length 可选,列长度(默认值255)
(9) precision 可选,列十进制精度(decimal precision)(默认值0)
(10) scale 可选,如果列十进制数值范围(decimal scale)可用,在此设置(默认值0)
@Id,标识这个属性是实体类的唯一识别的值。
注意:这个注解只能标注单一列构成的主键,
如tbl_grade那种有两个字段组成的联合主键由其他注解标识
hibernate 接口
===============
Configuration
进行配置信息的管理(数据库连接,映射)
用来产生SessionFactory
可以在configure方法中指定hibernate配置文件
只需关注一个方法即:buildSessionFactory
private static org.hibernate.SessionFactory sessionFactory;
private static Configuration configuration = new Configuration();
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static String configFile = CONFIG_FILE_LOCATION;
static {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
SessoinFactory(维护数据库连接池)
a) 用来产生和管理Session(生产和管理连接)
b) 通常情况下每个应用只需要一个SessionFactory
c) 除非要访间多个数据库的情况
d) 关注两个方法即:openSession getCurrentsession
i. open session每次都是新的,需要close
ii. getCurrentsession从上下文找,如果有,用旧的,如果没有,建新的,可以使用事务(session.getTransaction().commit()提交后,session就不存在了)
getCurrentSession创建的session会和绑定到当前线程,而openSession不会
getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭
上下文配置(即在hibernate.cfg.xml)中,需要配置:
(需要注意,这里的current_session_context_class属性有几个属性值:jta 、 thread 常用 , custom、managed 少用 )
a).thread使用connection 单数据库连接管理事务
b).jta (java transaction api) Java 分布式事务管理 (多数据库访问),jta 由中间件提供(JBoss WebLogic 等, 但是tomcat 不支持)
Session session = sf.openSession();
session.beginTransaction();
session.save(tea);
session.getTransaction().commit();
session.close();
1 Session
a) 管理一个数据库的任务单元(简单说就是增 删 改 查)
b) 方法(CRUD)
i. Save()
ii. delete
iii. load 从数据库中取出一条记录到内存中,转换为javabean(persistent状态)。返回代理对象,然后使用属性的时候才会真正从数据库中拿
iv. get 直接向数据库发送sql语句拿到对象,直接加载,不会延迟。
*hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要第一时间获取到真实的数据,否则返回null。无论是load还是get,都会首先査找缓存(一级缓存),如果没有,才会去数据库査找,调用clear()方法可以强制清除session缓存。调用***clear()**方法可以强制清除session缓存。
vi. updates
用来更新detached对象,更新完成后转为persistent状态; 更新transient对象会报错; 更新自己设定id的transient对象可以(数据库有对应记录); persistent状态的对象只要设定(如:t.setName…)不同字段就会发生更新。
或者通过sql语句
Query q = session.createQuery("update Teacher t set t.name='wangee' where t.id=1");
q.executeUpdate();
vii. flush()
tea.setName("new111");
session.flush();
tea.setName("new111111");
当session的事务提交后,会强制将内存(session缓存)与数据库同步.默认情况下是session的事务提交(commit)时才同步!
对象的三种状态
三种状态:
a) transient(瞬态):内存中一个对象,没ID,缓存中也没有
在数据库中没有与之匹配的数据,只是一个普通的JavaBean
没有纳入session的管理
b) persistent(持久态):内存中有,缓存中有,数据库有(ID)
persistent状态的对象在数据库中有与之匹配的数据
纳入了session的管理(session中有map数据结构,map中的key对应id,value对应存储的对象引用,相当于缓存的作用,提高效率)
在清理缓存(脏数据检查)的时候,会和数据库同步
c) detached(脱管态):内存有,缓存没有,数据库有ID
在数据库中有与之匹配的数据
session关闭了,没有纳入session的管理(没有缓存了,session中的map没有了)
关系映射
one to one
one to many
many to many
hibernate缓存体系
一级缓存:
Session 有一个内置的缓存,其中存放了被当前工作单元加载的对象。
每个Session 都有自己独立的缓存,且只能被当前工作单元访问。
一个线程对应一个session,一个线程可以看成一个用户。也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了
list与iterator
list:每次使用都重新发送sql语句,不使用session缓存,取全部数据。
iterator:可以使用session缓存,每次查询都先取出id,将id对应的对象放在缓存中。
二级缓存:
SessionFactory的外置的可插拔的缓存插件。其中的数据可被多个Session共享访问。sessionFactory控制的进程级缓存是全局共享的缓存
SessionFactory的内置缓存:存放了映射元数据,预定义的Sql语句
经常被访问,改动不大,数量有限的对象是很适合放在二级缓存中
load默认使用二级缓存,iterator默认使用二级缓存
list默认向二级缓存中添加数据,查询的时候不用
查询时使用缓存的实现过程为:首先查询一级缓存中是否具有需要的数据,如果没有,查询二级缓存,如果二级缓存中也没有,此时再执行查询数据库的工作。要注意的是:此3种方式的查询速度是依次降低的。
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>//cache category
<property name="cache.use_query_cache">true</property>//list会将结果放入缓存
另外需要在javabean中做注解@cache
一级缓存与二级缓存
Session的生命期往往很短,存在于Session内部的第一级最快缓存的生命期当然也很短,所以第一级缓存的命中率是很低的。其对系统性能的改善也是很有限的。当然,这个Session内部缓存的主要作用是保持Session内部数据状态同步。并非是hibernate为了大幅提高系统性能所提供的