前述
在前一篇博客中,我记录了Hibernate的环境的搭建,并且熟悉了一次Hibernate执行的过程。我在后面的博客中,会记录更多关于hibernate中的知识点。总共会有以下所有内容:
- 整合log4j
- 配置文件
- API
- Hibernate CRUD操作
- PO对象的操作
- 一级缓存
- 二级缓存
- 关联关系
- 抓取策略
- HQL
- 事务隔离
一.整合log4j
log4j是Apache组织的一个开源项目,用于将日志信息输送到控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器。我们可以控制每一条日志的输出格式,还可以通过定义日志信息的级别,而这一切操作,都可以通过配置文件来完成。
- 引入jar包:到log4j官网就可以下载到。
- 配置文件log4j.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53#The five logging levels used by Log are (in order):
#
#1. DEBUG (the least serious)
#2. INFO
#3. WARN
#4. ERROR
#5. FATAL (the most serious)
#Set root logger level to INFO and append to stdout
log4j.rootLogger=INFO,stdout,file
#设置log的级别为INFO意味着INFO级别以下如DEBUG的信息不会输出
#其中,Log4j提供的appender有以下几种:
#org.apache.log4j.ConsoleAppender(控制台),
#org.apache.log4j.FileAppender(文件),
#org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
#org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
#org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
#其中,Log4j提供的layout有以几种:
#org.apache.log4j.HTMLLayout(以HTML表格形式布局),
#org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
#org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
#org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
#Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:
#%m 输出代码中指定的消息
#%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
#%r 输出自应用启动到输出该log信息耗费的毫秒数
#%c 输出所属的类目,通常就是所在类的全名
#%t 输出产生该日志事件的线程名
#%n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
#%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2016年5月1日 22:10:28,921
#%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
#stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%p]%-d{yyyy-MM-dd HH\:mm\:ss}[%c\:%L] %m%n
#file
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=/output.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p]%-d{yyyy-MM-dd HH\:mm\:ss}[%c\:%L] %m%n
#log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.file.File=/output.html
#log4j.appender.file.DatePattern='.'yyyy-MM-dd
#log4j.appender.file.layout=org.apache.log4j.HTMLLayout
#log4j.appender.file.layout.ConversionPattern=[%p]%-d{yyyy-MM-dd HH\:mm\:ss}[%c\:%L] %m%n
#Print only messages of level ERROR or above in the package noModule.
log4j.logger.noModule=INFO
二.核心配置文件hibernate.cfg.xml
1 | <hibernate-configuration> |
Hibernate映射配置文件
1 | <hibernate-mapping> |
三.常用API
- 读取并解析配置文件 Configuration conf = new Configuration().configure();
- 读取并解析映射信息,创建SessionFactory SessionFactory sf = conf.buildSessionFactory();
- 打开Session Session session = sf.openSession();
- 开始一个事务(增删改操作必须,查询操作可选) Transaction tx = session.beginTransaction();
- 数据库操作 session.save(user);//或其它操作
- 提交事务(回滚事务) tx.commit();(tx.rollback();)
- 关闭session session.close();
Configuration是默认加载hibernate.cfg.xml这个文件的,但也提供了重载的方法
public Configuration configure(String resource)
public Configuration configure(URL url)
public Configuration configure(File configFile)SessionFactiory:Configuration的实例会根据当前的配置信息,构造SessionFactory实例。SessionFactory是线程安全的,一般情况下一个应用中一个数据库共享一个SessionFactory实例。
Hibernate的SessionFactory接口提供Session类的实例,Session类用于完成对数据库的操作。由于SessionFactory实例是线程安全的(而Session实例不是线程安全的),所以每个操作都可以共用同一个SessionFactory来获取Session。
从XML文件读取配置信息构建SessionFactory
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();Session:一般的持久化方法(CRUD)都是通过Session来调用的,Session是非线程安全的。
Session的创建与关闭 :Session是一个轻量级对象,通常将每个Session实例和一个数据库事务绑定,也就是每执行一个数据库事务,都应该先创建一个新的Session实例,在使用Session后,还需要关闭Session。
Session的创建
创建SessionFactory后,就可以通过SessionFactory创建Session实例,通过SessionFactory创建Session实例的代码如下。
Session session=sessionFactory.openSession();
创建Session后,就可以通过创建的Session进行持久化操作了。
Session的关闭
在创建Session实例后,不论是否执行事务,最后都需要关闭Session实例,释放Session实例占用的资源。
关闭Session实例的代码如下:
session.close();
下面来看一下:getCurrentSession 与 openSession() 的区别
1.getCurrentSession创建的session会和绑定到当前线程,而openSession不会。
2 getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭
3.getCurrentSession () 使用当前的session,openSession() 重新建立一个新的session
这里getCurrentSession本地事务(本地事务:jdbc)时 要在配置文件里进行如下设置
如果使用的是本地事务(jdbc事务)
1 | <property name="hibernate.current_session_context_class">thread</property> |
如果使用的是全局事务(jta事务)1
<property name="hibernate.current_session_context_class">jta</property>
openSession() 与 getCurrentSession() 有何不同和关联呢?
在SessionFactory启动的时候Hibernate会根据配置创建相应的CurrentSessionContext,在getCurrentSession()被调用的时候,实际被执行的方法是CurrentSessionContext.currentSession()。在currentSession()执行时,如果当前Session为空,currentSession会调用SessionFactory的openSession所以getCurrentSession()对于avaEE来说是更好的获取Session的方法。
- Transaction: hibernate把AutoCommit关掉了,所以如果想要进行数据操作,又不开启事务的话,数据库就不会有任何改变。