【问题标题】:Are @Transactional and packagesToScan are interlinked?@Transactional 和 packagesToScan 是否相互关联?
【发布时间】:2015-08-15 17:14:29
【问题描述】:

com.service.EmployeeService 有方法 create createEmployee 调用 dao 类下的方法,即 com.dao.EmployeeDao(having EntityManager as dependency)。 现在我想用@Transactional 使方法createEmployee 具有事务性。是否必须声明包com.service 在 spring 配置文件中的packagesToScan 下?

我的意思是必须在packagesToScan下使用@Transactional声明类的包才能使其工作?

仅供参考,我参考了 how-does-spring-transactional-really-work 以了解 Spring 事务在内部是如何工作的

【问题讨论】:

    标签: java spring hibernate transactions


    【解决方案1】:

    @Transactional 用于事务管理的类或方法,而 spring 使用 packagesToScan 扫描实体类上的注释

    <property name="packagesToScan">
                <list>
                    <value>com.xyz.EntityName</value>
                </list>
            </property>
    

    我在我的 DaoImpl 方法 (CRUD) 上使用了 @Transactional,并在实体上使用了 packagesToScan 以供 spring 选择。

    当你使用 spring 和 hibernate 时,它​​是 spring 类的责任,即 org.springframework.orm.hibernate4.LocalSessionFactoryBean 如&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"&gt; 而不是 Hibernate 的新 Configuration().configure().buildSessionFactory()

    此外,在 hibernate 中,您使用

    告诉 hibernate 考虑使用注释的实体,就像在 hibrnate.cfg.xml 中一样
    <mapping class="com.hiber.hr.Countries"/>
    <mapping class="com.hiber.hr.Departments"/>
    

    同样你需要通过 packagesToScan 属性告诉 spring。

    Spring 内部调用了 Hibernate 的 org.hibernate.cfg.Configuration 类的 addAnnotatedClass 方法

    从 Spring 调用的 Hibernate 方法:-

    public Configuration addAnnotatedClass(Class annotatedClass)
       {
         XClass xClass = reflectionManager.toXClass(annotatedClass);
        metadataSourceQueue.add(xClass);
        return this;
       }
    

    【讨论】:

    • 但是我的问题是,当我们已经在 J​​PA 实体上使用 @Entity 注释时,为什么还需要 packagesToScan。如果我不提及packagesToScan 下的实体而只使用@Entity 怎么办?
    • 我在上面添加了几行来回答您的评论。
    • 好的,知道了。但是还有一个问题,为什么 spring 需要知道 JPA 实体的位置?它对他们做了什么样的处理?
    • Hibernate 对它们进行的相同类型的处理。它不是位置,而是 packageName.className,hibernate 在映射 class="packageName.className" 时使用的方式与 Spring 使用它的方式完全相同。 Spring 在内部将相同的委托给休眠,如上所示。
    【解决方案2】:

    Transactional 使 Spring bean 方法具有事务性。

    packagesToScan 是 Spring sessionFactory / entityManagerFactory beans 的一个属性,它告诉他们在哪里可以找到 JPA 实体。

    它们是完全正交的。实体不是 Spring bean。事务 Spring bean 不是必须由 SessionFactory / EntityManagerFactory 找到的实体。

    【讨论】:

    • 我相信packagesToScan属性用于搜索需要注入EntityManager的实体。对吧?
    • 没有。 EntityManager 未注入实体。它使用 PersistenceContext 注释注入 Spring bean,通常是 DAO/Repositories。实体中没有注入任何内容,因为实体不是 Spring bean。
    • 正如你所说的 packagesToScan ... tell them where to find JPA entities. 所以在我的例子中 createEmployee Employee 将是 JPA 实体,因为我使用了 @Entity 。但是我的问题是,当我们已经在 J​​PA 实体上使用 @Entity 注释时,为什么还需要 packagesToScan。如果我不提及packagesToScan 下的实体而只使用@Entity 怎么办?
    • @Entity 告诉类是一个实体。但是 Spring 没有什么神奇的方法可以知道所有带有 @Entity 注释的类。它通过扫描类来帮助你找到它们,但为了避免扫描整个类路径,你可以通过告诉它扫描哪个包来找到它们来帮助它。
    • @JB Nizet 非常感谢
    猜你喜欢
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    相关资源
    最近更新 更多