使用Spring作为JPA容器

时间:2010-06-09 20:47:36

标签: spring jpa

我发现这篇文章讨论了如何将Spring用作JPA容器:

http://java.sys-con.com/node/366275

在此之前我从未使用过Spring,并且正在努力完成这项工作并希望有人能帮助我。

在文章中,它指出你需要使用@Transactional和带有@PersistenceContext的方法/字段来注释Spring bean,以便提供事务支持并注入实体管理器。

有没有将bean定义为“Spring Bean”的东西?我有一个bean类,它使用泛型实现对实体的CRUD操作:

@Transactional
public class GenericCrudServiceBean implements GenericCrudService
{
    @PersistenceContext(unitName="MyData")
    private EntityManager em;

    @Override
    @PersistenceContext
    public <T> T create(T t)
    {
        em.persist(t);
        return t;
    }

    @Override
    @PersistenceContext
    public <T> void delete(T t)
    {
        t = em.merge(t);
        em.remove(t);
    }
...
...
...
    @Override
    @PersistenceContext
    public List<?> findWithNamedQuery(String queryName)
    {
        return em.createNamedQuery(queryName).getResultList();
    }
}

最初我只有这个peristence context注释:

@PersistenceContext(unitName="MyData")
private EntityManager em;

但是在调用findWithNamedQuery时有一个空em。然后我也注释了这些方法,但是em仍然是null(没有注入?)。

我想知道这是否与我的bean没有被认为是“春天”有关。

我已经完成了配置,我可以按照文章中的说明进行操作,包括在我的context.xml文件中设置以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:tx="http://www.springframework.org/schema/tx"
    tx:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="MyData" />
        <property name="dataSource" ref="dataSource" />
        <property name="loadTimeWeaver"
            class="org.springframework.classloading.ReflectiveLoadTimeWeaver" />
        <property name="jpaVendorAdapter" ref="jpaAdapter" />
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:MySID" />
        <property name="username" value="user" />
        <property name="password" value="password" />
        <property name="initialSize" value="3" />
        <property name="maxActive" value="10" />
    </bean>

    <bean id="jpaAdapter"
        class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
        <property name="databasePlatform"
            value="org.eclipse.persistence.platform.database.OraclePlatform" />
        <property name="showSql" value="true" />
    </bean>

    <bean
        class="org.springframework.ormmjpa.support.PersistenceAnnotationBeanPostProcessor" />
    <tx:annotation-driven />
</beans>

我猜这些属于context.xml文件,因为该文章从未明确说明哪个文件是“应用程序上下文”文件。如果这是错的,请告诉我。

3 个答案:

答案 0 :(得分:0)

为了让一个类成为一个spring bean,它必须是:

  • 映射为<bean id=".." class="..">或使用@Component注释,@Service或类似的原型注释
  • 由您实例化。如果你想让spring连接你的依赖项,你必须让它实例化你的类。所以没有new GenericCrudServiceBean()(即使使用new运算符也有“技巧”来启用依赖注入,但它们适用于特殊情况)

为了不需要实例化您的类,您必须在控制器和服务的“前面”放置一些东西。对于Web框架,这将是Servlet,或者是servlet的补充,它通过ApplicationContext的spring来处理你的类 - 使用Spring MVC DispatcherServlet - 在JSF中使用了自定义弹簧ELResolver

根据您的框架,查找“X spring integration”。

对于你的情况 - Portlets - spring有Portlet MVC

答案 1 :(得分:0)

  

在文章中,它指出你需要使用@Transactional和带有@PersistenceContext的方法/字段来注释Spring bean,以便提供事务支持并注入实体管理器。

这是正确的,您不应只在private EntityManager em属性上添加@PersistenceContext

  

是否有将bean定义为“Spring Bean”的东西?

这是一个由Spring容器管理的bean(即Spring管理它的生命周期,用其他Spring bean连接它等)。这当然意味着您正在创建一个Spring容器。

  

我猜这些属于context.xml文件,因为该文章从未明确说明哪个文件是“应用程序上下文”文件。如果这是错的,请告诉我。

这属于一个应用程序上下文文件,它只是一个XML文件,只要您告诉Spring容器加载它,名称就不重要了。实际上,这是一个大问题:如何运行代码

本文运行来自测试用例的示例,该测试用例扩展了一个提供Spring支持的Spring类(我的意思是它将为您创建Spring容器)并允许告诉Spring要加载哪个应用程序上下文文件(在这种情况下,my-spring-config.xml)提供getConfigLocations方法:

package org.bookguru;

import org.springframework.test.jpa.AbstractJpaTests;

public class BookInventorySystemTest extends AbstractJpaTests {

    private BookInventorySystem bookInventorySystem;

    public void setBookInventorySystem(
       BookInventorySystem bookInventorySystem) {
       this.bookInventorySystem = bookInventorySystem;
    }

    protected String[] getConfigLocations() {
       return new String[] {"/my/path/my-spring-config.xml"};
    }
} 

那么,你如何运行你的代码?

答案 2 :(得分:0)

值得注意的是Spring documentation

中的以下内容
  

@EnableTransactionManagement并且只在它们定义的相同应用程序上下文中查找bean上的@Transactional。这意味着,如果在WebApplicationContext中为DispatcherServlet添加注释驱动配置,它只检查控制器中的@Transactional bean ,而不是你的服务。有关更多信息,请参见第17.2节“DispatcherServlet”。

当您使用portlet时,这意味着您必须在portlet上下文中启用注释驱动的事务。这可能是你的问题。

今天打击了我 - 我有一个多portlet应用程序,并希望在applicationcontext中设置所有数据库bean。这很好,并且在我的所有测试中都有效。

然而,当部署到portlet容器时,我的portlet特定bean都没有知道该事务 - 原因是因为我缺少我的portletcontext。我读完手册后就清楚了....