#mysql #hibernate #spring-mvc #jpa-2.0 #spring-data
#mysql #спящий режим #spring-mvc #jpa-2.0 #spring-данные
Вопрос:
Возникли проблемы с сохранением объекта JPA через CrudRepository. Кажется, что он возвращает исходный объект, который был передан ему, без сохранения объекта в базе данных. Я знаю, что это неправильный способ сделать это, но для целей тестирования, если я помещаю экземпляр TransactionSynchronizationManager перед сохранением, кажется, что он сохраняется правильно. Это наводит меня на мысль, что, возможно, есть проблема с менеджером транзакций?
Кроме того, если я удаляю репозиторий и использую Entity Manager (em), я получаю тот же результат, однако, если я вызываю em.flush(), я получаю исключение «Transactionrequiredexception, транзакция не выполняется».
@Transactional
public class UserServiceImpl implements UserService{
@Autowired
private UserRepository userRepository;
@Autowired
private EntityManagerFactory emf;
@Override
@Transactional(readOnly=false)
public User save(User user) {
// EntityManager em = emf.createEntityManager();
//Object persists when adding following line
// TransactionSynchronizationManager.bindResource(emf , new EntityManagerHolder(em));
return userRepository.save(user);
}
}
@ComponentScan(basePackages = {"..."})
@Import(value={DataContextConfig.class,SecurityConfig.class})
public class AppConfig{
}
@Configuration
@ComponentScan(basePackages = {".."})
@Import(DataConfig.class)
public class DataContextConfig {
}
@Configuration
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
@EnableJpaRepositories(value={"com.repository"}, entityManagerFactoryRef="entityManagerFactory", transactionManagerRef="transactionManager")
@PropertySource("classpath:data.properties")
public class DataConfig {
...
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory((EntityManagerFactory) entityManagerFactory());
return txManager;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factory.setPackagesToScan("...");
factory.setJpaPropertyMap(jpaProperties());
factory.setDataSource(dbSource());
return factory;
}
@Bean
public DriverManagerDataSource dbSource(){
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
driverManagerDataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
driverManagerDataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
driverManagerDataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return driverManagerDataSource;
}
}
Я загрузил небольшой проект, который изолирует исключение. Zip и запустить AccountTester.class http://www14.zippyshare.com/v/81636273/file.html
Комментарии:
1. Вы не открывали сеанс раньше
save
. а ты?2. Очень полезно, если поставить полную трассировку стека.
3. Нет трассировки стека. Сбой без ошибок
4. Я думаю, что вы пытаетесь
userRepository.save(user);
без открытия сеанса гибернации и trnsaction, по крайней мере, по этой причине вы получаете ошибку `Транзакция не выполняется`.5. У меня есть @EnableTransactionManagement(mode =AdviceMode. ASPECTJ) Аннотации внутри класса @Config.
Ответ №1:
Согласно вашему образцу проекта. Ниже приведены единственные классы, измененные, чтобы избежать вашей TransactionRequiredException: no transaction is in progress
проблемы и успешно вставить учетную запись:
package com.jpa.base.repository;
import com.jpa.base.entity.Account;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface AccountRepository extends CrudRepository<Account, Long> {
public Account findByEmailAddress(@Param(value = "emailAddress") String emailAddress);
public Account findByAccountId(@Param(value = "accountId") Long accountId);
}
Вам нужно пометить свой репозиторий Spring Data JPA @Repository
(не ваш сервис). Смотрите здесь
package com.jpa.base.service.impl;
import com.jpa.base.entity.Account;
import com.jpa.base.repository.AccountRepository;
import com.jpa.base.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("accountService")
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountRepository accountRepository;
@Override
@Transactional(readOnly = true)
public Account findByAccountId(Long accountId) {
return accountRepository.findByAccountId(accountId);
}
@Override
@Transactional(readOnly = true)
public Account findByEmailAddress(String emailAddress) {
return accountRepository.findByEmailAddress(emailAddress);
}
@Override
@Transactional
public Account save(Account account) {
return accountRepository.save(account);
}
}
Обратите внимание на изменения, связанные с удалением @Repository
из службы (должно быть в вашем интерфейсе хранилища Spring Data JPA) и использованием accountRepository
для сохранения вашей сущности в вашем save(...)
методе.
Не уверен, почему вы пытались использовать EntityManagerFactory
для создания нового EntityManager
(если вам действительно нужен EntityManager
экземпляр, вы должны просто ввести настроенный EntityManager
, а не заводской). Это также является причиной вашего TransactionRequiredException
.
В любом случае, зачем беспокоиться обо всем этом, когда вы можете просто использовать свой репозиторий для сохранения своей сущности. Запуск вашего AccountTester
now обеспечивает желаемую функциональность:
...
Hibernate: insert into account (email_address, name, version) values (?, ?, ?)
INFO : com.jpa.base.entity.AccountTester - Account Saved: Account Id: 3, Email Address:james.brown@outlook.com, Name: James Brown, Version: 0
Ответ №2:
Оказывается, было несколько @EnableTransactionManagement(mode=AdviceMode.ASPECTJ) аннотации внутри приложения. Это было причиной проблемы, после удаления объекта в классе Neo4j @Configuration проблема исчезла.