我发现这篇文章讨论了如何将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文件,因为该文章从未明确说明哪个文件是“应用程序上下文”文件。如果这是错的,请告诉我。
答案 0 :(得分:0)
为了让一个类成为一个spring bean,它必须是:
<bean id=".." class="..">
或使用@Component
注释,@Service
或类似的原型注释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。我读完手册后就清楚了....