Ten błąd pojawia się podczas próby wywołania metody „persist” w celu zapisania modelu jednostki do bazy danych w mojej aplikacji internetowej Spring MVC. Nie mogę znaleźć żadnego posta lub strony w Internecie, które mogą odnosić się do tego konkretnego błędu. Wygląda na to, że coś jest nie tak z fasolą EntityManagerFactory, ale jestem całkiem nowy w programowaniu Spring, więc wydaje mi się, że wszystko jest dobrze zainicjowane i zgodnie z różnymi artykułami samouczków w sieci.
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";
}
}
java
spring
spring-mvc
web-applications
Michał Bil
źródło
źródło
@Transaction
.Odpowiedzi:
Miałem ten sam problem i oznaczyłem metodę jako
@Transactional
i zadziałała.AKTUALIZACJA: sprawdzanie dokumentacji wiosennej wygląda na to, że domyślnie PersistenceContext jest typu Transaction, dlatego metoda musi być transakcyjna ( http://docs.spring.io/spring/docs/current/spring-framework-reference/ html / orm.html ):
źródło
@Transactional
adnotacji wywoła metodę z@Transactional
adnotacją w tym samym pliku klasy, również zostaniesz dotknięty tym błędem (właśnie to miałem do czynienia).@Transactional
, która również działa. Nie jestem pewien, czy to właściwa droga, ale wygląda na to, że działa dobrze ...Otrzymałem ten wyjątek podczas próby użycia niestandardowej metody deleteBy w repozytorium danych wiosny. Podjęto próbę wykonania operacji z klasy testowej JUnit.
Wyjątek nie występuje w przypadku korzystania z
@Transactional
adnotacji na poziomie klasy JUnit.źródło
@Transactional
na poziomie klasy może maskować możliwe problemy testowe, które manipulują różnymi transakcjami w usługach.@Trasactional
metody repozytorium, ponieważ jest to miejsce, w którym faktycznie wchodzę w interakcję z bazą danych i działa dobrze.Ten błąd kazał mi leczyć przez trzy dni, sytuacja, w której się znalazłem, spowodowała ten sam błąd. Postępując zgodnie ze wszystkimi radami, które znalazłem, bawiłem się konfiguracją, ale bezskutecznie.
W końcu znalazłem to, różnica, wykonywana usługa była zawarta w zwykłym jar, problem okazał się być taki, że AspectJ nie traktuje tak samo instancji usługi. W efekcie proxy po prostu wywoływało metodę bazową bez wykonywania całej normalnej magii Springa przed wywołaniem metody.
W końcu adnotacja @Scope umieszczona na serwisie jak na przykładzie rozwiązała problem:
@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(); } }
Opublikowana przeze mnie metoda to metoda usuwania, ale adnotacje wpływają na wszystkie metody utrwalania w ten sam sposób.
Mam nadzieję, że ten post pomoże komuś innemu, kto zmagał się z tym samym problemem podczas ładowania usługi ze słoika
źródło
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
do klasy DAO implementującej interfejs jest naprawdę ważne. Spędziłem cały dzień, aby rozwiązać ten błąd, a twoje rozwiązanie jako jedyne działa. Dziękuję Ci bardzo!Miałem ten sam błąd, ponieważ zmieniłem konfigurację XML na java.
Chodziło o to, że nie przeprowadziłem migracji
<tx:annotation-driven/>
tagu, jak sugerował Stone Feng.Więc właśnie dodałem
@EnableTransactionManagement
zgodnie z sugestią tutaj Konfigurowanie transakcji sterowanych adnotacjami wiosną w klasie @Configuration i działa terazźródło
boardRepo.deleteByBoardId (id);
W obliczu tego samego problemu. GOT javax.persistence.TransactionRequiredException: brak EntityManager z dostępną rzeczywistą transakcją dla bieżącego wątku
Rozwiązałem to dodając adnotację @Transactional nad kontrolerem / usługą.
źródło
Miałem ten sam problem i dodałem
tx:annotation-driven
wapplicationContext.xml
i to działało.źródło
Wystąpił ten sam błąd podczas uzyskiwania dostępu do metody już transakcyjnej z adnotacjami z metody nietransakcyjnej w tym samym komponencie:
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();
Naprawiłem błąd, wywołując metodę executeQuery () na komponencie, do którego się odwołujemy:
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 } }
źródło
Dodanie
org.springframework.transaction.annotation.Transactional
adnotacji na poziomie klasy do klasy testowej rozwiązało problem.źródło
Tylko uwaga dla innych użytkowników szukających odpowiedzi na ten błąd. Innym częstym problemem jest:
(Istnieją sposoby i sposoby korzystania z AspectJ, ale refaktoryzacja będzie znacznie łatwiejsza)
Potrzebujesz więc klasy wywołującej i klasy, która przechowuje
@transactional
metody.źródło
Dla nas problem sprowadzał się do tych samych ustawień kontekstu w wielu plikach konfiguracyjnych. Sprawdź, czy nie zduplikowano następujących elementów w wielu plikach konfiguracyjnych.
<context:property-placeholder location="classpath*:/module.properties"/> <context:component-scan base-package="...." />
źródło
Miałem ten sam kod błędu, gdy użyłem
@Transaction
niewłaściwej metody / poziomu działania.methodWithANumberOfDatabaseActions() { methodA( ...) methodA( ...) } @Transactional void methodA( ...) { ... ERROR message }
Oczywiście musiałem umieścić to
@Transactional
tuż nad metodąmethodWithANumberOfDatabaseActions()
.To rozwiązało komunikat o błędzie w moim przypadku.
źródło
Jeśli masz
@Transactional // Spring Transactional class MyDao extends Dao { }
i superklasy
class Dao { public void save(Entity entity) { getEntityManager().merge(entity); } }
i dzwonisz
@Autowired MyDao myDao; myDao.save(entity);
nie otrzymasz Spring TransactionInterceptor (który daje Ci transakcję).
Oto, co musisz zrobić:
@Transactional class MyDao extends Dao { public void save(Entity entity) { super.save(entity); } }
Niewiarygodne, ale prawdziwe.
źródło
Usunąłem tryb z
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" />
aby to działało
źródło
Miałem ten problem od kilku dni i nic, co znalazłem w Internecie, nie pomogło mi, zamieszczam tutaj swoją odpowiedź na wypadek, gdyby pomogła komukolwiek innemu.
W moim przypadku pracowałem nad mikrousługą wywoływaną za pośrednictwem komunikacji zdalnej, a moja adnotacja @Transactional na poziomie usługi nie była odbierana przez zdalny serwer proxy.
Dodanie klasy delegata między warstwami usługi i dao i oznaczenie metody delegata jako transakcyjnej rozwiązało ten problem.
źródło
To nam pomogło, może pomoże innym w przyszłości.
@Transaction
nie działał dla nas, ale to:@ConditionalOnMissingClass("org.springframework.orm.jpa.JpaTransactionManager")
źródło