为什么openSession不工作,但getCurrentSession在Spring Hibernate中起作用 [英] Why doesn't openSession work but getCurrentSession works in Spring Hibernate

查看:131
本文介绍了为什么openSession不工作,但getCurrentSession在Spring Hibernate中起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一个Spring Hibernate应用程序示例,了解Spring hibernate集成是如何工作的。

这是我的applicationContext.xml

 < beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3 .org / 2001 / XMLSchema-instancexmlns:p =http://www.springframework.org/schema/p
xmlns:aop =http://www.springframework.org/schema/aop xmlns:context =http://www.springframework.org/schema/context
xmlns:jee =http://www.springframework.org/schema/jeexmlns:tx =http: //www.springframework.org/schema/tx
xmlns:task =http://www.springframework.org/schema/task
xsi:schemaLocation =http:// www。 springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org /schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context /spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework。 org / schema / tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema /task/spring-task-3.2.xsd\">

< context:component-scan base-package =com.general/>

< tx:annotation-driven />

< bean id =dataSource
class =org.springframework.jdbc.datasource.DriverManagerDataSource>
< property name =driverClassNamevalue =oracle.jdbc.driver.OracleDriver/>
< property name =urlvalue =jdbc:oracle:thin:@localhost:1521:orcl/>
< property name =usernamevalue =system/>
< property name =passwordvalue =admin_123/>
< / bean>

< bean id =sessionFactory
class =org.springframework.orm.hibernate4.LocalSessionFactoryBean>
< property name =dataSourceref =dataSource>< / property>
< property name =packagesToScanvalue =com.general>< / property>
< property name =hibernateProperties>
<道具>
< prop key =hibernate.dialect> org.hibernate.dialect.Oracle10gDialect< / prop>
< prop key =hibernate.show_sql> true< / prop>
< /道具>
< / property>
< / bean>

< bean id =transactionManager
class =org.springframework.orm.hibernate4.HibernateTransactionManager>
< property name =sessionFactoryref =sessionFactory>< / property>
< / bean>
< / beans>

然后,我的服务类就是这样

  package com.general; 

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

$ b @Service(employeeService)
public class EmployeeServiceImpl implements EmployeeService {
$ b $ @Autowired
private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;

$ b @Transactional
public void saveEmployee(Employee emp){
Session session = sessionFactory.getCurrentSession(); //。openSession();
session.save(emp);
}

}

我的主类是 p>

  public class App {

public static void main(String [] args){
System .out.println(load context);
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(applicationContext.xml);
Employee em = new Employee();
em.setId(1l);
em.setName(John);

EmployeeService emService =(EmployeeService)context.getBean(employeeService);
emService.saveEmployee(em);
}

}

如果我使用getCurrentSession方法,那么它运行良好,雇员被保存到数据库中,但是如果我使用openSession方法,则不会触发SQL查询,因此不会将任何数据保存到数据库中。



我不知道为什么会发生这种情况。可能是我对getCurrentSession()和openSession()没有正确的理解。

解决方案

事实上,您有 @Transactional @Service 带注释的类中的方法以及 TransactionManager 意味着整个事务生命周期将被Spring管理。



当调用 saveEmployee 方法时,Spring将打开一个 Session ,启动一个事务,执行你的代码,提交事务并关闭 Session 。它启动的 Session 绑定到当前线程,并可通过 getCurrentSession()获得。



如果您改为使用 openSession(),您打开完全不相关 Session ,而不是由Spring的 TransactionManager 管理。因此,交易不会被提交,并且 Session 不会被关闭,除非您自己做。


I have written a sample Spring Hibernate application o understand how Spring hibernate integration works.

Here is my applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

    <context:component-scan base-package="com.general" />

    <tx:annotation-driven />

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" />
        <property name="username" value="system" />
        <property name="password" value="admin_123" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean ">
        <property name="dataSource" ref="dataSource"></property>
        <property name="packagesToScan" value="com.general"></property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
</beans>

Then, my service class is like that

package com.general;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;


@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService{

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Transactional
    public void saveEmployee(Employee emp) {
        Session session = sessionFactory.getCurrentSession();//.openSession();
        session.save(emp);
    }

}

And my main class is

public class App {

    public static void main(String[] args) {
        System.out.println("load context");
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Employee em = new Employee();
        em.setId(1l);
        em.setName("John");

        EmployeeService emService = (EmployeeService) context.getBean("employeeService");
        emService.saveEmployee(em);
    }

}

If I run this application using getCurrentSession method, then it runs fine and employee is saved into the database but if i use openSession method, then no SQL query is fired and thus nothing is saved into the database.

I am not sure why this is happening. May be I don't have correct understanding of getCurrentSession () and openSession (). Can please someone let me know the reason behind it.

解决方案

The fact that you have @Transactional on a method in a @Service annotated class along with a TransactionManager means the whole transaction lifecycle will be managed by Spring.

When your saveEmployee method is called, Spring will open a Session, start a transaction, execute your code, commit the transaction and close the Session. The Session it starts is bound to the current thread and available through getCurrentSession().

If you instead use openSession(), you are opening a completely unrelated Session, not managed by Spring's TransactionManager. As such, the transaction won't be committed and the Sessionwon't be closed unless you do it yourself.

这篇关于为什么openSession不工作,但getCurrentSession在Spring Hibernate中起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆