c3p0配置
1 | <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --> |
hibernate 乐观锁
hibernate基于数据版本(Version)记录机制实现。为数据增加一个版本标识,一般是通过为数据库表增加一个“version”字段来实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。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
public class Conductor {
private Integer id;
private String name;
private Long version;
//setter/getter
}
Session session1=openSession();
Session session2=openSession();
Conductor stu1=(Conductor)session1.createQuery("from Conductor as a where a.name='Bob'").uniqueResult();
Conductor stu2=(Conductor)session2.createQuery("from Conductor as a where a.name='Bob'").uniqueResult();
//这时候,两个版本号是相同的
System.out.println("v1="+stu1.getVersion()+"--v2="+stu2.getVersion());
Transaction tx1=session1.beginTransaction();
stu1.setName("session1");
tx1.commit();
//这时候,两个版本号是不同的,其中一个的版本号递增了
System.out.println("v1="+stu1.getVersion()+"--v2="+stu2.getVersion());
Transaction tx2=session2.beginTransaction();
stu2.setName("session2");
tx2.rollback();
session2.close();
session1.close();
注解实现联合主键
联合主键用Hibernate注解映射方式主要有三种:
第一、将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,再将该类注解为@Embeddable
,最后在主类中(该类不包含联合主键类中的字段)保存该联合主键类的一个引用,并生成set和get方法,并将该引用注解为@Id
1
2
3
4
5
6
7
8
9
"JLEE01") (name=
public class Jlee01 implements Serializable{
private String address ;
private int age ;
private String email ;
private String phone ;
private JleeKey01 jleeKey ;
主键类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class JleeKey01 implements Serializable{
private long id;
private String name;
//setter/getter
public boolean equals(Object o) {
if(o instanceof JleeKey01){
JleeKey01 key = (JleeKey01)o ;
if(this.id == key.getId() && this.name.equals(key.getName())){
return true ;
}
}
return false ;
}
public int hashCode() {
return this.name.hashCode();
}
}
第二、将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,最后在主类中(该类不包含联合主键类中的字段)保存该联合主键类的一个引用,并生成set和get方法,并将该引用注解为@EmbeddedId
1
2
3
4
5
6
7
8
9
10
11
"JLEE02") (name=
public class Jlee02 {
private String address ;
private int age ;
private String email ;
private String phone ;
private JleeKey02 jleeKey ;
// 主键类:JleeKey02.java为普通java类即可。
第三、将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并要重写equals和hashcode.最后在主类中(该类包含联合主键类中的字段)将联合主键字段都注解为@Id
,并在该类上方将上这样的注解:@IdClass
(联合主键类.class)1
2
3
4
5
6
7
8
9
10
11
"JLEE03") (name=
.class) (JleeKey03
public class Jlee03 {
private long id ;
private String name ;
//setter/getter
}
hibernate.current_session_context_class
从3.0.1版本开 始,Hibernate增加了SessionFactory.getCurrentSession()
方法。一开始,它假定了采用JTA事务,JTA事务 定义了当前session的范围和上下文(scope and context)。Hibernate开发团队坚信,因为有好几个独立的JTA TransactionManager实现稳定可用,不论是否被部署到一个J2EE容器中,大多数(假若不是所有的)应用程序都应该采用JTA事务管理。 基于这一点,采用JTA的上下文相关session可以满足你一切需要。
更好的是,从3.1开始,SessionFactory.getCurrentSession()
的后台实现是可拔插的。因此,我们引入了新的扩展接口(org.hibernate.context.CurrentSessionContext)和新的配置参数(hibernate.current_session_context_class
),以便对什么是“当前session”的范围和上下文(scope and context)的定义进行拔插。
请参阅org.hibernate.context.CurrentSessionContext接口的Javadoc,那里有关于它的契约的详细讨论。它定义了单一的方法,currentSession()
,特定的实现用它来负责跟踪当前的上下文session。Hibernate内置了此接口的三种实现。
org.hibernate.context.JTASessionContext
- 当前session根据JTA来跟踪和界定。这和以前的仅支持JTA的方法是完全一样的。详情请参阅Javadoc。
org.hibernate.context.ThreadLocalSessionContext
- 当前session通过当前执行的线程来跟踪和界定。详情也请参阅Javadoc。
org.hibernate.context.ManagedSessionContext
- 当前session通过当前执行的线程来跟踪和界定。但是,你需要负责使用这个类的静态方法将Session实例绑定、或者取消绑定,它并不会打开(open)、flush或者关闭(close)任何Session。
前两种实现都提供了“每数据库事务对应一个session”的编程模型,也称作每次请求一个session。Hibernate session的起始和终结由数据库事务的生存来控制。假若你在纯粹的 Java SE之上采用自行编写代码来管理事务,而不使用JTA,建议你使用Hibernate Transaction API来把底层事务实现从你的代码中隐藏掉。如果你使用JTA,请使用JTA借口来管理Transaction。如果你在支持CMT的EJB容器中执行代码,事务边界是声明式定义的,你不需要在代码中进行任何事务或session管理操作。
hibernate.current_session_context_class
配置参数定义了应该采用哪个org.hibernate.context.CurrentSessionContext实现。注意,为了向下兼容,如果未配置此参数,但是存在org.hibernate.transaction.TransactionManagerLookup的配置,Hibernate会采用org.hibernate.context.JTASessionContext。一般而言,此参数的值指明了要使用的实现类的全名,但那三种内置的实现可以使用简写,即jta、thread和managed。
1、getCurrentSession()
与openSession()
的区别?
在 SessionFactory 启动的时候, Hibernate 会根据配置创建相应的 CurrentSessionContext ,在 getCurrentSession()
被调用的时候,实际被执行的方法是CurrentSessionContext.currentSession()
。在 currentSession()
执行时,如果当前 Session 为空,currentSession 会调用SessionFactory的openSession 。所以getCurrentSession()
对于 Java EE 来说是更好的获取 Session 的方法。
- 采用
getCurrentSession()
创建的session会绑定到当前线程中,而采用openSession()
创建的session则不会 - 采用
getCurrentSession()
创建的session在commit或rollback时会自动关闭,而采用openSession()
创建的session必须手动关闭
2、使用getCurrentSession()
需要在hibernate.cfg.xml文件中加入如下配置:
如果使用的是本地事务(jdbc事务)
1
<property name="hibernate.current_session_context_class">thread</property>
如果使用的是全局事务(jta事务)
1
<property name="hibernate.current_session_context_class">jta</property>
如果使用的是session的管理机制(不太常用)
1
<property name="hibernate.current_session_context_class">managed</property>
LOB creation as createClob() method threw error
如果运行时出现下面提示的话:1
2
3INFO [pool-2-thread-1] - HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
INFO [pool-2-thread-1] - HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException
INFO [pool-2-thread-1] - HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
可以忽略也可以将驱动降级,例如Oracle
,将class15替换成class14,Mysql
,将mysql-connector-java-5.1.21.jar 替换成 mysql-connector-java-5.1.6.jar,以此类推
createSQLQuery is not valid without active transaction
如果你报createSQLQuery is not valid without active transaction,请看这里
使用 Hibernate 的大多数应用程序需要某种形式的“上下文相关的”会话,特定的会话在整个特定的上下文范围内始终有效。然而,对不同类型的应用程序而言,要为什么是组成这种“上下文”下一个定义通常是困难的;不同的上下文对“当前”这个概念定义了不同的范围。
在 3.0 版本之前,使用 Hibernate 的程序要么采用自行编写的基于 ThreadLocal
的上下文会话,要么采用HibernateUtil 这样的辅助类,要么采用第三方框架(比如 Spring 或 Pico),它们提供了基于代理(proxy)或者基于拦截器(interception)的上下文相关的会话。从 3.0.1 版本开始,Hibernate 增加了SessionFactory.getCurrentSession() 方法。一开始,它假定了采用 JTA 事务,JTA 事务定义了当前 session 的范围和上下文(scope 和 context)。因为有好几个独立的 JTA TransactionManager 实现稳定可用,不论是否被部署到一个 J2EE 容器中,大多数(假若不是所有的)应用程序都应该采用 JTA 事务管理。基于这一点,采用 JTA 的上下文相关的会话可以满足你一切需要。
hibernate 增加配置1
<property name="hibernate.current_session_context_class">thread</property>
将getCurrentSession()
返回的session绑定到当前运行线程中。