私は永続化層としてJPAを利用してSpring MVCアプリケーションを作成しようとしています。残念ながら、Springがインジェクションしているように見えないので、EntityManagerにアクセスするとNullPointerExceptionが発生していました。私の設定はすべて@EnableWebMvcでアノテーションベースです。いくつかの検索の後、私は@TransactionalをDAOに、@EnableTransactionManagementを@Configurationクラスに追加しました。それから、DataSourceを持っていないというエラーが出ました。おそらく、@EnableTransactionManagementを持つクラスはTransactionManagementConfigurerを実装する必要があります。しかし、DataSourceの作成方法と、なぜpersistence.xmlから取得できないのかがわかりません。JPA with Spring MVC Annotationsによって設定されました
私はDAOにEntityManagerを注入しようとするとどんな助けにも大変感謝しています。
マイ@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 writeを実行するメソッドでこれを動作させる必要があります。私はコードを介してデバッグする場合、それは完璧にデータを取得するようだ。ただし、メソッドから戻ると、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;
}
}
これは、Hibernate固有のクラスを明示的に参照することは、基本的な実装と結び付いているように思えます。 また、理想的には、データソースにJNDIルックアップを使用しますが、それをどうやって行うのかよく分かりません。私はこれをしていないと仮定していますか? – Marshmellow1328
基本的な実装との結びつき - SpringなしでJPAを使用する場合でも、persistence.xmlに永続性プロバイダ設定を定義します。ここでは、それらを1つのメソッドentityManagerFactoryBean()のコードで定義します。しかし、あなたはそれらをxml設定ファイルに移すことができます) – dimas
元の答えでJNDIルックアップを使ってDataSourceを取得する方法の例を追加しました。 – dimas