Spring MVC Webアプリケーションでエンティティモデルをデータベースに保存するために「persist」メソッドを呼び出そうとすると、このエラーが発生します。この特定のエラーに関連している可能性があるインターネット上の投稿またはページを実際に見つけることができません。 EntityManagerFactory Beanに問題があるように思えますが、私はSpringプログラミングについてはかなり新しいので、すべてがうまく初期化されているようで、Webのさまざまなチュートリアル記事に従っているようです。
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/data/repository
http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">
<context:component-scan base-package="wymysl.Controllers" />
<jpa:repositories base-package="wymysl.repositories"/>
<context:component-scan base-package="wymysl.beans" />
<context:component-scan base-package="wymysl.Validators" />
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>
<bean id="passwordValidator" class="wymysl.Validators.PasswordValidator"></bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="Oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:Oracle:thin:@localhost:1521:xe" />
<property name="username" value="system" />
<property name="password" value="polskabieda1" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
</props>
</property>
</bean>
<mvc:annotation-driven />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
</bean>
<bean name="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:resources mapping="/resources/*" location="/resources/css/"
cache-period="31556926"/>
</beans>
RegisterController.Java
@Controller
public class RegisterController {
@PersistenceContext
EntityManager entityManager;
@Autowired
PasswordValidator passwordValidator;
@InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(passwordValidator);
}
@RequestMapping(value = "/addUser", method = RequestMethod.GET)
public String register(Person person) {
return "register";
}
@RequestMapping(value = "/addUser", method = RequestMethod.POST)
public String register(@ModelAttribute("person") @Valid @Validated Person person, BindingResult result) {
if(result.hasErrors()) {
return "register";
} else {
entityManager.persist(person);
return "index";
}
}
同じ問題があり、メソッドに@Transactional
のアノテーションを付けてもうまくいきました。
UPDATE:デフォルトでPersistenceContextがTransaction型であるように見える春のドキュメンテーションをチェックしているので、メソッドはtransactional( http://docs.spring.io/spring/docs/current/spring- framework-reference/html/orm.html ):
@PersistenceContextアノテーションにはオプションの属性タイプがあり、デフォルトはPersistenceContextType.TRANSACTIONです。このデフォルトは、共有EntityManagerプロキシを受け取るために必要なものです。別のPersistenceContextType.EXTENDEDはまったく別の問題です。これはいわゆる拡張EntityManagerになります。これはスレッドセーフではないため、Spring管理のシングルトンBeanなどの同時アクセスコンポーネントでは使用しないでください。拡張EntityManagerは、たとえばセッション内に存在するステートフルコンポーネントでのみ使用されることになっています。EntityManagerのライフサイクルは、現在のトランザクションとは関係なく、むしろアプリケーションに完全に依存しています。
Spring Data RepositoryでdeleteByカスタムメソッドを使用しようとしたときに、この例外が発生しました。操作はJUnitテストクラスから試行されました。
JUnitクラスレベルで@Transactional
アノテーションを使用しても例外は発生しません。
このエラーで私は3日間フォックスしていましたが、私が直面した状況でも同じエラーが発生しました。私が見つけることができたすべてのアドバイスに続いて、私は構成で遊んだが無駄に。
結局、私はそれを見つけました、違い、私が実行していたサービスは共通のjarファイルに含まれていました、問題はAspectJが同じサービスインスタンス化を扱わないことであることが判明しました。実際には、プロキシは、メソッド呼び出しの前に通常のSpringマジックをすべて実行せずに、基本となるメソッドを単純に呼び出していました。
最後に、例のようにサービスに配置された@Scopeアノテーションが問題を解決しました:
@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
@Transactional
public class CoreServiceImpl implements CoreService {
@PersistenceContext
protected EntityManager entityManager;
@Override
public final <T extends AbstractEntity> int deleteAll(Class<T> clazz) {
CriteriaDelete<T> criteriaDelete = entityManager.getCriteriaBuilder().createCriteriaDelete(clazz);
criteriaDelete.from(clazz);
return entityManager.createQuery(criteriaDelete).executeUpdate();
}
}
私が投稿したメソッドはdeleteメソッドですが、アノテーションはすべての永続メソッドに同じように影響します。
私はこの記事がjarからサービスをロードするときに同じ問題に苦しんでいる他の誰かに役立つことを願っています
XML構成からJava構成に切り替えたため、同じエラーが発生しました。
要点は、Stone Fengが示唆しているように、私は<tx:annotation-driven/>
タグを移行しないことでした。
そこで私はここで提案されているように@EnableTransactionManagement
を追加しました @Configurationクラスでの注釈駆動型トランザクションの設定 そしてそれは今動作します
私は同じ問題を抱えていました、そして私はtx:annotation-driven
をapplicationContext.xml
に追加しました、そして、それは働きました。
同じコンポーネント内の非トランザクションメソッドからすでにトランザクション注釈付きのメソッドにアクセスしたときにも同じエラーが発生しました。
Before:
@Component
public class MarketObserver {
@PersistenceContext(unitName = "maindb")
private EntityManager em;
@Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
public void executeQuery() {
em.persist(....);
}
@Async
public void startObserving() {
executeQuery(); //<-- Wrong
}
}
//In another bean:
marketObserver.startObserving();
自己参照コンポーネントでexecuteQuery()を呼び出すことでエラーを修正しました。
Fixed version:
@Component
public class MarketObserver {
@PersistenceContext(unitName = "maindb")
private EntityManager em;
@Autowired
private GenericApplicationContext context;
@Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
public void executeQuery() {
em.persist(....);
}
@Async
public void startObserving() {
context.getBean(MarketObserver.class).executeQuery(); //<-- Works
}
}
私たちにとって、問題は複数の設定ファイルの同じコンテキスト設定にありました。以下が複数の設定ファイルに重複していないことを確認してください。
<context:property-placeholder location="classpath*:/module.properties"/>
<context:component-scan base-package="...." />
間違ったメソッド/アクションレベルで@Transaction
を使用したときも同じエラーコードがありました。
methodWithANumberOfDatabaseActions() {
methodA( ...)
methodA( ...)
}
@Transactional
void methodA( ...) {
... ERROR message
}
もちろん@Transactional
をメソッドmethodWithANumberOfDatabaseActions()
の真上に置かなければなりませんでした。
それが私の場合のエラーメッセージを解決しました。
私は何日もこの問題を抱えていましたが、オンラインで見つけたものは何も私の役に立ちませんでした。
私の場合は、リモート処理を通じて呼び出されるマイクロサービスに取り組んでいましたが、サービスレベルでの@Transactionalアノテーションはリモートプロキシによって取得されていませんでした。
サービス層とdao層の間にデリゲートクラスを追加し、デリゲートメソッドをトランザクションとしてマークすることでこれが解決しました。
からモードを削除しました
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" />
これを機能させるために
boardRepo.deleteByBoardId(id);
同じ問題に直面しました。 GOTjavax.persistence.TransactionRequiredException:現在のスレッドで利用可能な実際のトランザクションを持つEntityManagerがない
コントローラ/サービスの上に@ Transactionalアノテーションを追加して解決しました。