有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Hibernate事务管理器在春季的配置

在我的项目中,我使用Hibernate进行编程事务划分。 每次在我的服务方法中,我都会写类似的东西

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
.. perform operation here
session.getTransaction().commit();

现在我要用声明式事务管理重构代码。我现在得到的

  <context:component-scan base-package="package.*"/>
  
  <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
    <property name="configurationClass">
        <value>org.hibernate.cfg.AnnotationConfiguration</value>
    </property>
  </bean>
  
  <tx:annotation-driven transaction-manager="txManager"/>
  
  
  <bean id="txManager"  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
         <ref local="mySessionFactory"/>
    </property>
  </bean>

服务级别:

@Service
public class TransactionalService {

    @Autowired
    private SessionFactory factory;
    
    @Transactional
    public User performSimpleOperation() {
        return (User)factory.getCurrentSession().load(User.class, 1L);
    }
}

简单的测试-

@Test
public void useDeclarativeDem() {
    FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext("spring-config.xml");
    TransactionalService b = (TransactionalService)ctx.getBean("transactionalService");
     User op = b.performSimpleOperation();
     op.getEmail();

当我尝试在事务方法之外获取用户电子邮件时,我得到了延迟初始化异常,电子邮件是我的一个简单字符串。Hibernate甚至不执行sql查询,直到我调用POJO上的任何getter

  1. 我做错了什么

  2. 这种方法有效吗

  3. 你能推荐任何在spring/hibernate上使用基于注释的配置的开源项目吗

更新

出于某种原因,如果我将getCurrentSession替换为openSession,那么这段代码可以正常工作。有人能解释一下吗


共 (2) 个答案

  1. # 1 楼答案

    来自Hibernate文档https://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch11.html#objectstate-loading

    请注意,如果没有匹配的数据库行,load()将引发不可恢复的异常。如果使用代理映射该类,load()只返回一个未初始化的代理,并且在调用代理的方法之前不会实际命中数据库。如果希望在不从数据库实际加载对象的情况下创建与对象的关联,这将非常有用。如果为类映射定义了批大小,它还允许将多个实例作为批加载

    从上面的文档中可以看出,在您的案例中,bean是用spring代理映射的,所以load只返回。因此,您需要使用get()而不是load(),后者总是命中数据库

  2. # 2 楼答案

    好了,我终于意识到问题出在哪里了。在上面的代码中,我使用了load而不是get。一场加载实际上并没有命中数据库。这就是为什么在@Transactional method之外会出现延迟初始化异常的原因

    如果我使用openSession而不是getCurrentSession,会话将在spring容器的作用域之外打开。结果会话没有关闭,它允许我读取@Transactional方法之外的对象属性