简而言之,我在尝试调用从 BaseRepository 扩展的接口中定义的方法时获得No transactional EntityManager available; nested exception is javax.persistence.TransactionRequiredException: No transactional EntityManager available
。
首先,我将公开与数据库相关的Spring配置。 这是我的spring-database.xml,包含与db相关的东西:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<context:component-scan base-package="com.cmc.articauno" />
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- <property name="location" value="classpath:application.properties" /> -->
<property name="ignoreUnresolvablePlaceholders" value="false"/>
<property name="ignoreResourceNotFound" value="false"/>
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" >
<list>
<value>com.cmc.articauno.dao.entidades</value>
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.default_schema">${database.schema}</prop>
<prop key="hibernate.dialect">${database.hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${database.hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${database.hibernate.format_sql}</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${database.driverClassName}" />
<property name="jdbcUrl" value="${database.connectionUrlSchema}" />
<property name="user" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="maxPoolSize" value="${database.maxPoolSize}" />
<property name="minPoolSize" value="${database.minPoolSize}" />
<property name="maxStatements" value="${database.maxStatements}" />
<property name="testConnectionOnCheckout" value="${database.testConnection}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven
transaction-manager="transactionManager"
proxy-target-class="true" />
<jpa:repositories
transaction-manager-ref="transactionManager"
base-package="com.my.app.dao.repository"
factory-class="com.my.app.dao.repository.base.BaseRepositoryFactoryBean" />
<!-- jpa auditor aware -->
<jpa:auditing auditor-aware-ref="customAuditorAware" />
</beans>
我使用基于接口的Spring Data存储库,我的所有存储库都扩展自 BaseRepository :
BaseRepository.java
@NoRepositoryBean
public interface BaseRepository <T extends BaseEntity, ID extends Serializable> extends JpaRepository<T, ID>
{
public T findByIdentificador(String identificador);
public boolean deleteByIdentificador(String identificador);
public boolean deleteByIdentificador(String identificador, boolean permanentDelete);
boolean existsByIdentificador(String identificador);
}
上面的接口有一个实现:
BaseRepositoryImpl
@NoRepositoryBean
public class BaseRepositoryImpl<T extends BaseEntity, ID extends Serializable>
extends SimpleJpaRepository<T, ID>
implements BaseRepository<T, ID>
{
private EntityManager entityManager;
private final Class<T> clazz;
private String entityName;
public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
this.entityManager = entityManager;
this.clazz = domainClass;
this.entityName = this.clazz.getSimpleName();
}
@Override
public T findByIdentificador(String identificador) {
List<T> result = new ArrayList<T>();
String jsql = String.format("select t from %s t where t.identificador='%s' "
+ "and t.activo='"+DaoConstants.ACTIVO+"'",
clazz.getSimpleName(), identificador);
Query query = entityManager.createQuery(jsql);
result = query.getResultList();
if (result != null && result.size() > 0 )
return result.get(0);
return null;
}
/* borrado logico */
@Transactional
@Override
public boolean deleteByIdentificador(String identificador) {
List<T> result = null;
String jsql = String.format("update %s t set t.activo='0' where t.identificador='%s'",
clazz.getSimpleName(), identificador);
Query query = entityManager.createQuery(jsql);
return query.executeUpdate() > 0;
}
@Override
public boolean existsByIdentificador(String identificador) {
List<T> result = new ArrayList<T>();
String jsql = String.format("select t from %s t where t.identificador='%s' "
+ "and t.activo='"+DaoConstants.ACTIVO+"'",
clazz.getSimpleName(), identificador);
Query query = entityManager.createQuery(jsql);
result = query.getResultList();
return result != null && result.size() > 0;
}
/* hace borrado fisico */
@Override
@Transactional
public boolean deleteByIdentificador(String identificador, boolean permanentDelete) {
if (!permanentDelete)
return false;
List<T> result = null;
String jsql = String.format("select t from %s t where t.identificador='%s'",
clazz.getSimpleName(), identificador);
Query query = entityManager.createQuery(jsql);
result = query.getResultList();
if (result != null && result.size() > 0) {
T entBorrar = result.get(0);
//entityManager.remove(entBorrar);
entityManager.remove(entityManager.contains(entBorrar) ? entBorrar : entityManager.merge(entBorrar));
entityManager.flush();
return true;
}
return false;
}
}
所有基础存储库都是因为我需要所有存储库的通用功能。后来所有的新回购都从基地延伸出来。我尝试使用的存储库是:
public interface RelPerFormRepository extends BaseRepository<RelPerFormEntity, Long>
{
@Query("select t from RelPerFormEntity t where t.idAutPersona = ?1 and t.idFormulario = ?2 order by createdDate desc")
public List<RelPerFormEntity> findAllByPersonaAndFormulario(Long idPersona, Long idFormulario);
@Modifying
@Transactional
@Query("delete from RelPerFormEntity r where r.idAutPersona = ?1 and r.idFormulario = ?2")
public Long deletePreviousFormResponses(Long idAutPersona, Long idFormulario);
@Transactional
public void deleteByIdAutPersonaAndIdFormulario(Long idAutPersona, Long idFormulario);
}
@Transactional和@Modifying取消注释我得到了这个例外,但是如果我删除了注释,我会在问题的开头显示异常。
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy86]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy86
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:212)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:447)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:333)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1719)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:113)
... 31 more