Spring JPA and persistence.xml

24

我正在尝试设置一个用于部署到Glassfish的Spring JPA Hibernate简单示例WAR。 我看到一些示例使用persistence.xml文件,而其他示例则不是这样做。 有些示例使用dataSource,而有些则不使用。目前我的理解是,如果我拥有:

<persistence-unit name="educationPU"
    transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>com.coe.jpa.StudentProfile</class>
    <properties>
        <property name="hibernate.connection.driver_class"
            value="com.mysql.jdbc.Driver" />
        <property name="hibernate.connection.url"
            value="jdbc:mysql://localhost:3306/COE" />
        <property name="hibernate.connection.username" value="root" />
        <property name="show_sql" value="true" />
        <property name="dialect" value="org.hibernate.dialect.MySQLDialect" />
    </properties>
</persistence-unit>
我可以成功部署,但是我的EntityManager没有被Spring注入。
我的applicationContext.xml:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="educationPU" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="StudentProfileDAO" class="com.coe.jpa.StudentProfileDAO">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="studentService" class="com.coe.services.StudentService">
</bean>

我的带有 EntityManager 的类:

public class StudentService {
private String  saveMessage;
private String  showModal;
private String modalHeader;
private StudentProfile studentProfile;
private String lastName;
private String firstName;

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

@Transactional
public String save()
{
    System.out.println("*** em: " + this.em); //em is null
    this.studentProfile= new StudentProfile();
    this.saveMessage = "saved";
    this.showModal = "true";
    this.modalHeader= "Information Saved";
    return "successs";
}

我的web.xml文件:

  <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

我是否遗漏了某些部分,才能使Spring注入到StudentService中的“em”?

5个回答

13

只是确认一下,你可能已经...

你是否包含了

<!--  tell spring to use annotation based congfigurations -->
<context:annotation-config />
<!--  tell spring where to find the beans -->
<context:component-scan base-package="zz.yy.abcd" />

您的应用程序context.xml中有多少位?

另外,我不确定您是否能够在这种设置下使用jta事务类型?这不需要数据源管理的连接池吗?因此,请尝试使用RESOURCE_LOCAL。


4

我有些困惑。你是将PU注入到服务层而不是持久层中吗?我不理解。

我将持久层注入到服务层中。服务层包含业务逻辑并划分事务边界。它可以在一个事务中包含多个DAO。

我也不理解你的save()方法中的魔法。数据是如何保存的?

在生产环境中,我会像这样配置spring:

<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/ThePUname" />

除了在web.xml中进行引用外

对于单元测试,我会这样做:

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:dataSource-ref="dataSource" p:persistence-xml-location="classpath*:META-INF/test-persistence.xml"
    p:persistence-unit-name="RealPUName" p:jpaDialect-ref="jpaDialect"
    p:jpaVendorAdapter-ref="jpaVendorAdapter" p:loadTimeWeaver-ref="weaver">
</bean>

2

如果有人想要使用纯Java配置来代替Hibernate的xml配置,请使用以下代码:

您可以在Spring中完全不使用persistence.xml来配置Hibernate,如下所示:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
{
Map<String, Object> properties = new Hashtable<>();
properties.put("javax.persistence.schema-generation.database.action",
"none");
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect"); //you can change this if you have a different DB
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(adapter);
factory.setDataSource(this.springJpaDataSource());
factory.setPackagesToScan("package name");
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
factory.setJpaPropertyMap(properties);
return factory;
}

由于您没有使用persistence.xml,因此您需要创建一个返回数据源的bean,并在上述设置数据源的方法中指定它:

@Bean
public DataSource springJpaDataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost/SpringJpa");
dataSource.setUsername("tomcatUser");
dataSource.setPassword("password1234");
return dataSource;
}

然后您需要在此配置文件上使用@EnableTransactionManagement注释。现在当您放置该注释时,您必须创建一个最后的bean:

@Bean
public PlatformTransactionManager jpaTransactionManager()
{
return new JpaTransactionManager(
this.entityManagerFactoryBean().getObject());
}

现在,不要忘记在处理数据库的方法上使用@Transactional注解。
最后,请不要忘记在您的存储库中注入EntityManager(该存储库类应该在其上有@Repository注解)。

0

我使用JPA/Hibernate和Spring设置了一个测试应用程序,并且我的配置与你的镜像相同,只是我创建了一个数据源并将其注入到EntityManagerFactory中,并将数据源特定属性从persistenceUnit中移出并放入了数据源中。通过这两个小更改,我的实体管理器成功地被注入。


-2
这可能有点老了,但如果有人遇到同样的问题,请尝试在PersistenceContext注释中将unitname更改为name:

@PersistenceContext(unitName="educationPU")

@PersistenceContext(name="educationPU")

10
哦?@PersistenceContext 的可选属性 name 用于查找注入的实体管理器,但是它在 persistence.xml 中没有对应的元素。如果这对你有效,那么我认为这只是与缺少 unitName 相关的幸运副作用(这种情况下的行为是供应商特定的)。但这是不正确的。 - Pascal Thivent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接