Tôi đang cố gắng tạo ứng dụng Spring MVC tận dụng JPA cho lớp kiên trì của nó. Thật không may, tôi đã nhận được một NullPointerException khi truy cập EntityManager vì Spring dường như không tiêm nó. Cấu hình của tôi là tất cả dựa trên chú thích với @EnableWebMvc. Sau khi tìm kiếm, tôi đã thêm @Transactional vào DAO và @EnableTransactionManagement vào lớp @Configuration của tôi. Sau đó, tôi nhận được một lỗi về việc không có một DataSource. Giả sử, một lớp có @EnableTransactionManagement cần phải thực hiện TransactionManagementConfigurer. Tuy nhiên, tôi đang gặp vấn đề tìm ra cách tạo DataSource cũng như lý do tại sao nó không thể lấy nó từ persistence.xml của tôi.JPA với Spring MVC được định cấu hình qua chú thích
Tôi sẽ đánh giá rất cao bất kỳ trợ giúp nào trong việc cố gắng đưa EntityManager được tiêm vào DAO của tôi.
lớp @Configuration My
@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 My
@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;
}
}
Mã Cập nhật My
Tôi đã đạt đến điểm mà nó hầu như tất cả các công trình. EntityManager đang được tiêm đúng cách. Tuy nhiên, các giao dịch không hoạt động. Tôi gặp lỗi nếu tôi cố gắng sử dụng phương pháp RESOURCE_LOCAL vì vậy tôi đang xem xét các giao dịch được quản lý bởi JTA. Khi tôi thêm @Transactional vào bất kỳ phương thức DAO nào của mình, tôi nhận được lỗi "Giao dịch được đánh dấu để quay lại" mà không có thêm chi tiết nào trong bất kỳ tệp nhật ký nào để hỗ trợ khắc phục sự cố. Nếu tôi xóa chú thích khỏi lựa chọn chỉ đọc cơ bản, lựa chọn sẽ hoạt động hoàn toàn tốt (không chắc chắn liệu tôi có nên đặt chú thích trên các phương thức chỉ chọn) hay không. Tuy nhiên, tôi rõ ràng cần điều này làm việc trên phương pháp thực hiện db viết. Nếu tôi gỡ lỗi thông qua mã, có vẻ như để lấy dữ liệu hoàn toàn tốt. Tuy nhiên, khi nó trả về từ phương thức, javax.transaction.RollbackException bị ném. Từ sự hiểu biết của tôi về tất cả mọi thứ, nó có vẻ như là nếu ngoại lệ xảy ra trong xử lý sau phương pháp AOP.
My @Configuration lớp
@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;
}
}
Điều này liên quan đến tôi một cách rõ ràng rằng bạn tham chiếu rõ ràng các lớp Hibernate cụ thể vì nó dường như buộc nó vào triển khai cơ bản. Ngoài ra, lý tưởng, tôi muốn sử dụng tra cứu JNDI cho nguồn dữ liệu, nhưng không quen thuộc với cách tôi làm điều đó. Tôi giả định điều này là không làm điều đó? – Marshmellow1328
Về việc buộc phải triển khai cơ bản - ngay cả khi bạn sử dụng JPA mà không có Spring, bạn xác định các thiết lập của nhà cung cấp bền vững trong persistence.xml. Ở đây bạn định nghĩa chúng trong mã trong một phương thức entityManagerFactoryBean(). Nhưng bạn có thể chuyển chúng sang tệp cấu hình xml) – dimas
Tôi đã thêm ví dụ về cách lấy DataSource qua tra cứu JNDI trong câu trả lời ban đầu của tôi. – dimas