永続層にJPAを活用するSpringMVCアプリケーションを作成しようとしています。残念ながら、Springがそれを注入していないように見えるため、EntityManagerにアクセスするときにNullPointerExceptionが発生していました。私の構成はすべて@EnableWebMvcを使用したアノテーションベースです。検索した後、DAOに@Transactionalを追加し、@Configurationクラスに@EnableTransactionManagementを追加しました。次に、データソースがないというエラーが発生しました。おそらく、@EnableTransactionManagementを持つクラスはTransactionManagementConfigurerを実装する必要があります。ただし、データソースを作成する方法と、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<MyClass> query = criteriaBuilder.createQuery( MyClass.class );
// more code here, but it breaks by this point
return myData;
}
}
私の更新されたコード
ほぼすべてが機能するようになりました。EntityManagerが適切に挿入されています。ただし、トランザクションは機能していません。RESOURCE_LOCALアプローチを使用しようとするとエラーが発生するため、JTA管理のトランザクションを調べています。DAOメソッドのいずれかに@Transactionalを追加すると、トラブルシューティングに役立つログファイルにそれ以上の詳細がない「ロールバック用にマークされたトランザクション」エラーが発生します。基本的な読み取り専用選択から注釈を削除すると、選択は完全に正常に機能します(選択専用メソッドに注釈を付ける必要があるかどうかはわかりません)。ただし、db書き込みを実行するメソッドでこれを実行する必要があることは明らかです。コードをデバッグすると、データは完全に正常に取得されているようです。ただし、メソッドから戻ると、javax.transaction.RollbackExceptionがスローされます。
私の@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;
}
}