我正在尝试创建一个利用JPA作为其持久层的Spring MVC应用程序.不幸的是,我在访问EntityManager时遇到了NullPointerException,因为Spring似乎没有注入它.我的配置是基于注释的@EnableWebMvc.经过一番搜索,我在我的DAO上添加了@Transactional,在我的@Configuration类上添加了@EnableTransactionManagement.然后我得到一个关于没有DataSource的错误.据推测,具有@EnableTransactionManagement的类需要实现TransactionManagementConfigurer.但是,我在弄清楚如何创建DataSource以及为什么它无法从我的persistence.xml中获取它时遇到了问题.
我非常感谢任何尝试将EntityManager注入我的DAO的帮助.
我的@Configuration类
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.example.myapp")
public class MvcConfig extends WebMvcConfigurerAdapter
implements TransactionManagementConfigurer {
private static final boolean CACHE_ENABLED = true;
private static final String TEMPLATE_PATH = "/WEB-INF/freemarker";
private static final String TEMPLATE_SUFFIX = ".ftl";
private static final Logger LOG = Logger.getLogger( MvcConfig.class );
@Override
public void addResourceHandlers( ResourceHandlerRegistry registry ) {
registry.addResourceHandler( "/stylesheets/**" ).addResourceLocations( "/stylesheets/" );
}
@Bean
public FreeMarkerConfigurer configureFreeMarker() {
final FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath( TEMPLATE_PATH );
return configurer;
}
@Bean
public ViewResolver configureViewResolver() {
final FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setCache( CACHE_ENABLED );
resolver.setSuffix( TEMPLATE_SUFFIX );
return resolver;
}
@Bean
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager();
}
}
我的DAO
@Component
@Transactional
public class MyDAO {
private static final Logger LOG = Logger.getLogger( MyDAO.class );
@PersistenceContext
private EntityManager entityManager;
public MyClass getMyClass() {
LOG.debug( "getMyClass()" );
final CriteriaQuery
我的更新代码
我已经达到了几乎所有工作的程度. EntityManager正在正确注入.但是,交易无效.如果我尝试使用RESOURCE_LOCAL方法,我会收到错误,因此我正在查看JTA托管事务.当我在任何DAO方法上添加@Transactional时,我得到一个“标记为回滚的事务”错误,在任何日志文件中没有进一步的详细信息以帮助进行故障排除.如果我从基本的只读选择中删除注释,则选择将完全正常工作(不确定我是否应该将注释放在仅选择方法上).但是,我显然需要处理执行db写入的方法.如果我通过代码调试,它似乎完全检索数据.但是,当它从方法返回时,会抛出javax.transaction.RollbackException.根据我对一切的理解,似乎异常发生在AOP后方法处理中.
我的@Configuration类
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.example.myapp")
public class MvcConfig extends WebMvcConfigurerAdapter {
private static final boolean CACHE_ENABLED = true;
private static final String TEMPLATE_PATH = "/WEB-INF/freemarker";
private static final String TEMPLATE_SUFFIX = ".ftl";
private static final Logger LOG = Logger.getLogger( MvcConfig.class );
@Override
public void addResourceHandlers( ResourceHandlerRegistry registry ) {
registry.addResourceHandler( "/stylesheets/**" ).addResourceLocations( "/stylesheets/" );
}
@Bean
public FreeMarkerConfigurer configureFreeMarker() {
final FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath( TEMPLATE_PATH );
return configurer;
}
@Bean
public ViewResolver configureViewResolver() {
final FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setCache( CACHE_ENABLED );
resolver.setSuffix( TEMPLATE_SUFFIX );
return resolver;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new JtaTransactionManager();
}
@Bean
public AbstractEntityManagerfactorybean entityManagerfactorybean() {
LocalEntityManagerfactorybean factory = new LocalEntityManagerfactorybean();
factory.setPersistenceUnitName( "my_db" );
return factory;
}
}
@Bean
public LocalContainerEntityManagerfactorybean entityManagerfactorybean() {
LocalContainerEntityManagerfactorybean factorybean =
new LocalContainerEntityManagerfactorybean();
factorybean.setDataSource(dataSource());
factorybean.setPackagesToScan(new String[] {"com.dimasco.springjpa.domain"});
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowsql(true);
//vendorAdapter.setGenerateDdl(generateDdl)
factorybean.setJpaVendorAdapter(vendorAdapter);
Properties additionalProperties = new Properties();
additionalProperties.put("hibernate.hbm2ddl.auto","update");
factorybean.setJpaProperties(additionalProperties);
return factorybean;
}
@Bean
public DataSource dataSource() {
final ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass(driverClass);
} catch (PropertyVetoException e) {
throw new RuntimeException(e);
}
dataSource.setJdbcUrl(jdbcUrl);
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setMinPoolSize(3);
dataSource.setMaxPoolSize(15);
dataSource.setDebugUnreturnedConnectionStackTraces(true);
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerfactorybean().getObject());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
希望对你有帮助)
编辑:
您可以使用JNDI查找获取数据源:
@Bean
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
更多细节你可以找到in this article.有JndiDatasourceConfig类的例子.
编辑2:
我在我的项目中使用了persistence.xml,但它是空的:
我没有在我的java配置中指定任何持久性单元名称.