使用hibernate时,接口SessionFactory中获取session的方法挺多:openSession, getCurrentSession.如果使用spring,则有更多的用法。这些用法不免迷惑,他们分别是什么意思,哪些会自动提交呢?
下面是我结合实例与源码的分析。
没有使用spring管理的情况
主要区别openSession()和openCurrentSession(),openSession()即打开一个session,但程序中直接使用它,而是使用getCurrentSession(),典型用法如下(没有使用spring申明式管理管理事务)
private List listEvents() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List result = session.createQuery("from Event").list();
session.getTransaction().commit();
return result;
}
openCurrentSession()即获取当前上下文session
/**
* Obtains the current session. The definition of what exactly "current"
* means controlled by the {@link org.hibernate.context.CurrentSessionContext} impl configured
* for use.
* <p/>
* Note that for backwards compatibility, if a {@link org.hibernate.context.CurrentSessionContext}
* is not configured but a JTA {@link org.hibernate.transaction.TransactionManagerLookup}
* is configured this will default to the {@link org.hibernate.context.JTASessionContext}
* impl.
*
* @return The current session.
*
* @throws HibernateException Indicates an issue locating a suitable current session.
*/
public org.hibernate.classic.Session getCurrentSession() throws HibernateException;
private CurrentSessionContext buildCurrentSessionContext() {
String impl = properties.getProperty( Environment.CURRENT_SESSION_CONTEXT_CLASS );
// for backward-compatability
if ( impl == null && transactionManager != null ) {
impl = "jta";
}
if ( impl == null ) {
return null;
}
else if ( "jta".equals( impl ) ) {
if ( settings.getTransactionFactory().areCallbacksLocalToHibernateTransactions() ) {
log.warn( "JTASessionContext being used with JDBCTransactionFactory; auto-flush will not operate correctly with getCurrentSession()" );
}
return new JTASessionContext( this );
}
else if ( "thread".equals( impl ) ) {
return new ThreadLocalSessionContext( this );
}
else if ( "managed".equals( impl ) ) {
return new ManagedSessionContext( this );
}
else {
try {
Class implClass = ReflectHelper.classForName( impl );
return ( CurrentSessionContext ) implClass
.getConstructor( new Class[] { SessionFactoryImplementor.class } )
.newInstance( new Object[] { this } );
}
catch( Throwable t ) {
log.error( "Unable to construct current session context [" + impl + "]", t );
return null;
}
}
}
从上面获取CurrentSessionContext的方法中看出,current session是由配置文件制定,默认是jta。
如果使用spring管理,切勿配置该项,默认将为springContextProvider
current_session_context_class thread
使用spring管理
spring中的HibernateTemplate有对hibernate的封装,有很多便捷的方法,在DAO实现中
@Override
public Magic read(int id) {
return super.getHibernateTemplate().get(Magic.class, id);
}
但是如果需要自己使用复杂的组合查找,可以使用excute(new HiberanteCallback())
public <T> T get(final Class<T> entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return executeWithNativeSession(new HibernateCallback<T>() {
@SuppressWarnings("unchecked")
public T doInHibernate(Session session) throws HibernateException {
if (lockMode != null) {
return (T) session.get(entityClass, id, lockMode);
}
else {
return (T) session.get(entityClass, id);
}
}
});
}
这样调用获取的session是通过下面这个方法
/**
* Return a Session for use by this template.
* <p>Returns a new Session in case of "alwaysUseNewSession" (using the same
* JDBC Connection as a transactional Session, if applicable), a pre-bound
* Session in case of "allowCreate" turned off, and a pre-bound or new Session
* otherwise (new only if no transactional or otherwise pre-bound Session exists).
* @return the Session to use (never <code>null</code>)
* @see SessionFactoryUtils#getSession
* @see SessionFactoryUtils#getNewSession
* @see #setAlwaysUseNewSession
* @see #setAllowCreate
*/
protected Session getSession() {
if (isAlwaysUseNewSession()) {
return SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor());
}
else if (isAllowCreate()) {
return SessionFactoryUtils.getSession(
getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
}
else if (SessionFactoryUtils.hasTransactionalSession(getSessionFactory())) {
return SessionFactoryUtils.getSession(getSessionFactory(), false);
}
else {
try {
return getSessionFactory().getCurrentSession();
}
catch (HibernateException ex) {
throw new DataAccessResourceFailureException("Could not obtain current Hibernate Session", ex);
}
}
}
SessionFactoryUtil中的逻辑如下
/**
* Get a Hibernate Session for the given SessionFactory. Is aware of and will
* return any existing corresponding Session bound to the current thread, for
* example when using {@link HibernateTransactionManager}. Will create a new
* Session otherwise, if "allowCreate" is <code>true</code>.
* <p>Same as {@link #getSession}, but throwing the original HibernateException.
* @param sessionFactory Hibernate SessionFactory to create the session with
* @param entityInterceptor Hibernate entity interceptor, or <code>null</code> if none
* @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
* Session on transaction synchronization (may be <code>null</code>)
* @param allowCreate whether a non-transactional Session should be created
* when no transactional Session can be found for the current thread
* @return the Hibernate Session
* @throws HibernateException if the Session couldn't be created
* @throws IllegalStateException if no thread-bound Session found and
* "allowCreate" is <code>false</code>
*/
private static Session doGetSession(
SessionFactory sessionFactory, Interceptor entityInterceptor,
SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
throws HibernateException, IllegalStateException {
Assert.notNull(sessionFactory, "No SessionFactory specified");
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if (sessionHolder != null && !sessionHolder.isEmpty()) {
// pre-bound Hibernate Session
Session session = null;
if (TransactionSynchronizationManager.isSynchronizationActive() &&
sessionHolder.doesNotHoldNonDefaultSession()) {
// Spring transaction management is active ->
// register pre-bound Session with it for transactional flushing.
session = sessionHolder.getValidatedSession();
if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {
logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");
TransactionSynchronizationManager.registerSynchronization(
new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));
sessionHolder.setSynchronizedWithTransaction(true);
// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
FlushMode flushMode = session.getFlushMode();
if (flushMode.lessThan(FlushMode.COMMIT) &&
!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
session.setFlushMode(FlushMode.AUTO);
sessionHolder.setPreviousFlushMode(flushMode);
}
}
}
else {
// No Spring transaction management active -> try JTA transaction synchronization.
session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);
}
if (session != null) {
return session;
}
}
logger.debug("Opening Hibernate Session");
Session session = (entityInterceptor != null ?
sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());
// Use same Session for further Hibernate actions within the transaction.
// Thread object will get removed by synchronization at transaction completion.
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
logger.debug("Registering Spring transaction synchronization for new Hibernate Session");
SessionHolder holderToUse = sessionHolder;
if (holderToUse == null) {
holderToUse = new SessionHolder(session);
}
else {
holderToUse.addSession(session);
}
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
session.setFlushMode(FlushMode.MANUAL);
}
TransactionSynchronizationManager.registerSynchronization(
new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != sessionHolder) {
TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
}
}
else {
// No Spring transaction management active -> try JTA transaction synchronization.
registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
}
// Check whether we are allowed to return the Session.
if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
closeSession(session);
throw new IllegalStateException("No Hibernate Session bound to thread, " +
"and configuration does not allow creation of non-transactional one here");
}
return session;
}
可以看出,总体的获取session的顺序是先查看spring的transaction manager, 其次JTA, 再次调用getCurrentSession,在getCurrentSession也会有JTA的回退,可能有重复的地方。
分享到:
相关推荐
在进行任何数据库操作之前,都需要先获取一个`Session`。 2. `getTransaction()`:返回当前的`Transaction`实例,可以用来检查事务的状态或者提交或回滚事务。 3. `beginTransaction()`:启动一个新的数据库事务。在...
例如,ConnectionProvider负责数据库连接的获取和释放,而StatementExecutor处理SQL执行。 4. 查询机制:Hibernate Query Language (HQL) 和 Criteria API 是两种主要的查询方式。`org.hibernate.query`包下的Query...
- **读取配置**:`Configuration` 类可以加载并解析配置文件,从而获取数据库连接的信息、缓存策略以及其他配置参数。 - **构建SessionFactory**:通过调用 `Configuration` 的 `buildSessionFactory()` 方法来创建 ...
例如,获取所有用户的ID: ```java String sql = "SELECT id FROM User"; SQLQuery query = session.createSQLQuery(sql); List<Integer> ids = query.list(); ``` 接下来是QBC,即Query By Example,是一种基于...
例如,使用HQL获取所有用户: ```java String hql = "from User"; Query<User> query = session.createQuery(hql, User.class); List<User> users = query.getResultList(); ``` Criteria API查询: ```java ...
本帮助文档首先会介绍Hibernate的基本概念和工作原理,包括实体类、配置文件、Session工厂和Session接口等核心元素。通过学习,读者将理解如何创建Hibernate项目,定义实体类,以及设置相应的数据库连接信息。 接着...
例如,我们可以从查询结果集中获取BLOB对象,然后通过流操作读取其内容: ```java Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); ...
而立即加载则是在获取主对象时,同时加载其关联的对象。 这份文档深入浅出地讲解了这些核心概念,并且包含了大量的示例代码,无论是初学者还是经验丰富的开发者,都能从中受益。在实际开发中,配合阅读此文档,可以...
1. Hibernate配置与实体类:创建实体类,映射到数据库表,以及配置Hibernate的session工厂和事务管理。 2. Ajax与Hibernate的结合:通过Ajax请求更新数据库,Hibernate负责将Java对象转换为SQL语句执行。 3. ...
同时,Struts2的Action可以通过Spring的依赖注入获取到业务服务,降低了Action与业务层之间的耦合。 具体到这个"SSH整合架包jar",它可能包含了这三个框架的库文件,以及一些整合所需的配置文件,比如struts.xml、...
通过Session的get()或load()方法,可以获取数据库中的数据;更新实体后,使用Session的update()方法,将改动保存回去;删除实体时,调用Session的delete()方法。 此外,还要了解一对多、一对一、多对一和多对多等...
例如,如果新增了一个订单并添加到User的orders列表中,然后调用`session.saveOrUpdate(user)`,Hibernate会将新订单保存到数据库,并通过外键关联到用户。 但是,需要注意的是,级联操作可能导致数据一致性问题,...
Session session = factory.openSession(); Transaction tx = session.beginTransaction(); User user = new User(); user.setName("Jacky"); user.setAge(20); user.setContent(Hibernate.createClob("This is my...
4. 加载(Load)/获取(Get):根据ID获取持久化对象,Load会立即执行SQL查询,而Get在需要时才加载。 5. 查询(Query):通过HQL或Criteria API进行复杂查询,支持分页、排序、关联查询等。 六、关联映射 ...
3. 配置Struts2:修改Struts2的配置文件(如`struts-default.xml`或自定义的`struts.xml`),定义Action类和结果类型,并配置Spring插件,以便Action类可以从Spring容器中获取依赖。 4. 创建Action类:Action类通常...
Hibernate 通过 DataSource 对象自动管理数据库连接,开发者无需手动获取和释放连接。 #### 查询与检索 - **HQL(Hibernate Query Language)**:一种面向对象的查询语言,类似于 SQL,但更加面向对象。 - **...
- 这样,当我们通过Hibernate操作`Person`时,可以直接获取或设置其`Address`,反之亦然。 4. **示例代码**: - 创建和保存实体: ```java Session session = HibernateUtil.getSessionFactory().openSession()...
`getSession()`方法获取当前Session,`beginTransaction()`和`commit()`分别用于开始和提交事务,而`save()`方法用于保存实体到数据库。 最后,我们可以在Service或Controller中注入UserDAO,调用其方法来实现业务...
在这个测试程序中,我们可能会看到`SessionFactory`的获取和`Session`的打开、关闭过程。 5. **数据插入**:插入数据通常涉及以下步骤: - 开启`Session` - 创建实体对象,设置属性值 - 调用`Session`的`save()`...