Я пытаюсь создать приложение Spring MVC с использованием JPA для его уровня сохранения. К сожалению, я получал исключение NullPointerException при доступе к EntityManager как Spring, похоже, не вводит его. Моя конфигурация основана на аннотациях с помощью @EnableWebMvc. После некоторого поиска я добавил @Transactional в свой DAO и @EnableTransactionManagement в свой класс @Configuration. Затем я получил сообщение об отсутствии источника данных. Предположительно, класс с @EnableTransactionManagement должен реализовать TransactionManagementConfigurer. Однако у меня возникают проблемы с выяснением того, как создать DataSource, а также почему он не может получить его из моего persistence.xml.JPA с Spring MVC, сконфигурированный с помощью аннотаций
Я бы очень признателен за любую помощь в попытке получить 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. Когда я добавляю @Transactional по любому из моих методов DAO, я получаю ошибку «Транзакция, отмеченную для отката», без каких-либо подробностей в любых файлах журналов, чтобы помочь устранить неполадки. Если я удалю аннотацию из основного выбора только для чтения, выбор будет работать отлично (не уверен, что я даже должен помещать аннотацию в методы только для выбора). Однако я, очевидно, нуждаюсь в этом, работая над методами, которые выполняют 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;
}
}
Это мягко касается меня, что вы явно ссылаетесь на классы, связанные с Hibernate, поскольку, похоже, привязывают его к основной реализации. Кроме того, в идеале я бы использовал поиск JNDI для источника данных, но не знал, как это сделать. Я предполагаю, что это не так? – Marshmellow1328
О привязке к основной реализации - даже если вы используете JPA без пружины, вы определяете настройки поставщика сохранения в файле persistence.xml. Здесь вы определяете их в коде в одном методе entityManagerFactoryBean(). Но вы можете переместить их в файл конфигурации xml) – dimas
Я добавил пример, как получить DataSource через JNDI-поиск в моем первоначальном ответе. – dimas