首先是stacktrace:
org.springframework.dao.InvalidDataAccessApiUsageException:
Exception Description: No transaction is currently active; nested exception is javax.persistence.TransactionRequiredException:
Exception Description: No transaction is currently active
org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:316)
org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossible(DefaultJpaDialect.java:121)
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
com.sun.proxy.$Proxy299.saveAndFlush(Unknown Source)
我很确定这是一个愚蠢的错误,但我似乎无法找到我做错的事情:
@Service
:
@Service
public class BookInfoTracker implements InfoTracker
{
@Autowired
@Qualifier("bookTrackerRepository")
private TrackerRepository bookTrackerRepository;
public BookInfoTracker() {}
public BookInfoTracker (TrackerRepository bookTrackerRepository)
{
this.bookTrackerRepository = bookTrackerRepository;
}
@Transactional
@Override
public void track (long idBooking, String idLeg, String bookingEmail, int sequence, String event)
{
BookInfo ci = new BookInfo(idBooking, idLeg, bookingEmail, new Date(), sequence, event);
bookTrackerRepository.saveAndFlush(ci);
}
@Override
public int getSequenceFrom (long idBooking, String idLeg)
{
BookInfo tracked = findLastTrackedBookFrom(bookTrackerRepository.getLastTrackedBookByIdBookingAndIdLeg(idBooking, idLeg));
return null == tracked? 0 : tracked.getSequence()+1;
}
private BookInfo findLastTrackedBookFrom (List<BookInfo> trackedBooks)
{
return trackedBooks.isEmpty() ? null : trackedBooks.get(0);
}
}
jpa配置有一个基类:
@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
public abstract class JpaConfiguration
{
public JpaConfiguration ()
{
super();
}
public abstract LocalContainerEntityManagerFactoryBean buildEntityManagerFactory () throws SQLException;
@Bean(name = "transactionManager")
public PlatformTransactionManager buildTransactionManager () throws SQLException
{
JpaTransactionManager manager = new JpaTransactionManager();
LocalContainerEntityManagerFactoryBean factory = buildEntityManagerFactory();
manager.setEntityManagerFactory(factory.getObject());
return manager;
}
protected Database toDatabase (String databaseProductName)
{
for (Database database : Database.values())
if (databaseProductName.equalsIgnoreCase(database.toString())) return database;
return null;
}
protected LocalContainerEntityManagerFactoryBean initializeFactory (DataSource datasource, String persistenceUnitName, String... packagesToScan) throws SQLException
{
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(datasource);
factory.setPersistenceUnitName(persistenceUnitName);
factory.setPackagesToScan(packagesToScan);
EclipseLinkJpaVendorAdapter jpaAdaptor = new EclipseLinkJpaVendorAdapter();
jpaAdaptor.setDatabase(toDatabase(datasource.getConnection().getMetaData().getDatabaseProductName()));
jpaAdaptor.setShowSql(true);
factory.setJpaVendorAdapter(jpaAdaptor);
Properties jpaProperties = new Properties();
jpaProperties.put("eclipselink.ddl-generation", "none");
jpaProperties.put("eclipselink.ddl-generation.output-mode", "database");
jpaProperties.put("eclipselink.logging.level.sql", "FINE");
jpaProperties.put("eclipselink.logging.parameters", "true");
jpaProperties.put("eclipselink.cache.shared.default", "false");
jpaProperties.put("eclipselink.target-database", "MySQL");
jpaProperties.put("eclipselink.weaving","false");
factory.setJpaProperties(jpaProperties);
factory.afterPropertiesSet();
return factory;
}
}
然后是具体配置,子类:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.book.tracking.repositories"}, entityManagerFactoryRef="bookManagerFactory")
@Profile({"integration","test","release"})
public class JpaBookConfiguration extends JpaConfiguration
{
@Autowired
@Qualifier("bookDs")
private DataSource datasource;
@Override
@Bean(name = "bookManagerFactory")
public LocalContainerEntityManagerFactoryBean buildEntityManagerFactory () throws SQLException
{
return initializeFactory(datasource, "book.jpa", "com.book.tracking.entity");
}
}
然后是restservice:
@Controller
@ControllerAdvice
@RequestMapping("/bookservice")
public class BookRestService implements IBookService
{
private static final String LEG_VALID_PATTERN = "^(20)\\d\\d(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])_[A-Z]{3}-[A-Z]{3}$";
@Autowired
@Qualifier("bookBuilder")
private IBookBuilder bookBuilder;
@Autowired
@Qualifier("bookInfoTracker")
private InfoTracker bookInfoTracker;
@Autowired
@Qualifier("bookBookingEventsGenerator")
private BookingEventsGenerator bookBookingEventsGenerator;
public BookRestService (IBookBuilder bookBuilder,
InfoTracker infoTracker, BookingEventsGenerator bookBookingEventsGenerator)
{
this.bookBookingEventsGenerator = bookBookingEventsGenerator;
this.bookBuilder = bookBuilder;
this.bookInfoTracker = infoTracker;
}
public BookRestService ()
{
}
@Override
@RequestMapping(value="/generate/{idBooking}/{idLeg}")
public ResponseEntity<String> generateOneWayEvent (@PathVariable("idBooking") final long idBooking, @PathVariable("idLeg") final String idLeg)
{
return executeEventCommand(new EventCommand() {
@Override
public BookingEvent execute() {
BookingEvent event = bookBookingEventsGenerator.generateEventFrom(idBooking, idLeg);
return event;
}
}, idBooking, idLeg, "PUBLISH");
}
private ResponseEntity<String> executeEventCommand (EventCommand eventCommand, long idBooking, String idLeg, String operation)
{
try {
validate(idLeg);
logFor(idBooking, idLeg, "generateOneWayEvent");
HttpHeaders headers = modifyResponseAccordingTo(idLeg);
BookingEvent event = eventCommand.execute();
int sequence = bookInfoTracker.getSequenceFrom(idBooking, event.getBookingIdentifier());
String bookIcs = generateBookFrom(event, sequence);
logger.debug(bookInfoTracker.getClass());
//exception here
bookInfoTracker.track(idBooking, event.getBookingIdentifier(), bookBookingEventsGenerator.getContactEmail(), sequence, operation);
return new ResponseEntity<String>(bookIcs, headers, HttpStatus.OK );
} catch(LegNotFoundException lnfe){
logger.error(lnfe);
return new ResponseEntity<String>("Something went wrong", HttpStatus.NOT_FOUND);
}
}
/** other methods **/
}
好像不考虑@Transactional
注释?但是我使用了@EnableTransactionManagement
。你能在我的配置中看到错误吗?
更新:
@Configuration
@Profile({"integration", "release"})
public class IBookSpringConfiguration
{
@Autowired
@Qualifier("bookRestService")
private IBookService bookRestService;
@Autowired
@Qualifier("bookTrackerRepository")
private TrackerRepository bookTrackerRepository;
public ReloadableResourceBundleMessageSource getMessageBundle(){
ReloadableResourceBundleMessageSource bundle = new ReloadableResourceBundleMessageSource();
bundle.setBasename("book-message");
return bundle;
}
@Bean(name = "bookInfoTracker")
public InfoTracker getBookTrackingService(){
return new BookInfoTracker(bookTrackerRepository);
}
@Bean(name = "bookBuilder")
public IBookBuilder getBookBookingService(){
return new BookBuilder(getMessageBundle());
}
@Bean(name = "i18n")
public I18nUtilACL getI18n(){
return new I18nUtilBook(MultiSourceSiteCustomizer.getInstance());
}
@Bean(name = "bookBookingEventsGenerator")
public BookingEventsGenerator getBookBookingEventsGenerator(){
return new BookEventsGenerator();
}
@Bean(name = "bookBookingLegFactory")
public BookingLegEventsGenerator getBookBookingLegFactory(){
return new BookBookingLegEventsGenerator();
}
@Bean(name = "bookBookingFlightEventsGenerator")
public BookingEventsGenerator getBookBookingFlightEventsGenerator(){
return new BookEventsGenerator();
}
@Bean(name = "bookRestService")
@Scope("singleton")
public IBookService getBookRestService ()
{
return new BookRestService();
}
}
已解决,但不知道为什么:
我只是在JpaBookConfiguration中合并JpaConfiguration的父类和子类。现在它正在运作。不知道为什么。你可以解释吗?