2014-10-28 41 views
16

EntityManager örneğinde LocalContainerEntityManagerFactoryBean var.İlkbaharda paylaşılan EntityManager'da bir işlemi manuel olarak nasıl başlatabilirsiniz?

hızla ben aşağıdaki kodu çalıştırmak istiyorum, tam tablo içeriğini bırakmak için:

@Service 
public class DatabaseService { 
    @Autowired 
    private EntityManager em; 

    @Transactional 
    public void clear() { 
     em.createNativeQuery("TRUNCATE TABLE MyTable").executeUpdate(); 
    } 
} 

Sonuç:

ERROR org.springframework.integration.handler.LoggingHandler: javax.persistence.TransactionRequiredException: Executing an update/delete query 
    at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71) 
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) 
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:744) 

Bu değişikliği yaparsanız:

public void clear() { 
    em.getTransaction().begin(); 
    em.createNativeQuery("TRUNCATE TABLE MyTable").executeUpdate(); 
} 

Sonuç:

ERROR org.springframework.integration.handler.LoggingHandler: java.lang.IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:245) 
    at com.sun.proxy.$Proxy84.getTransaction(Unknown Source) 
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) 
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:744) 

Ben de yay veri JPA çalıştı, ama aynı zamanda başarısız: Yani

public interface MyRepository extends CrudRepository<MyEntity, Integer> { 
    @Query(value = "TRUNCATE TABLE MyTable", nativeQuery = true) 
    @Modifying 
    public void clear(); 
} 

, nasıl ortak bir yay bağlamında kesiğinin bir hareket oluşturmak ve çalıştırabilirim?

Bahar uygulaması kullanılarak başlatılır: SpringApplication.run(AppConfig.class, args); sahip:

@Bean 
public JpaTransactionManager transactionManager() { 
    return new JpaTransactionManager(emf); 
} 
+0

Lütfen bununla birlikte dahil olmak üzere tüm yığınları yükleyin. – m3th0dman

+3

Bunun yerine '@ Autowired' use' @ PersistenceContext' kullanmayın. –

+0

'@ PersistenceContext' hiçbir şeyi değiştirmedi. Stacktrace yukarıda güncellendi. – membersound

cevap

25

Sen imperatively işlem yönetmek için TransactionTemplate nesne kullanmalısınız:

transactionTemplate = new TransactionTemplate(platformTransactionManager); 

Ve yeni işlem kullanmak istiyorsanız sadece

transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); 
çağırmak:

transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
     @Override 
     protected void doInTransactionWithoutResult(TransactionStatus status) { 
      em.createNativeQuery("TRUNCATE TABLE MyTable).executeUpdate(); 
     } 
    }); 

TransactionTemplate oluşturmak için sadece PlatformTransactionManager enjekte kullanın

2

Çözüm olarak şimdi yaratılan EMF kullanarak, elle işlem başlayan yeni EntityManager açık.

@Autowired 
private EntityManagerFactory emf; 

public void clearTable() { 
    EntityManager em = emf.createEntityManager(); 
    EntityTransaction tx = em.getTransaction(); 
    tx.begin(); 
    em.createNativeQuery("TRUNCATE TABLE MyTable).executeUpdate(); 
    tx.commit(); 
    em.close(); 
} 

Muhtemelen bu ideal değil, ancak şu an için çalışıyor.

+1

'Transactional'ın çalışmaması için bir neden yok, kurulumunuzda bir sorun olmalı. Ayrıca, her iki çözüm de, sorunu gerçekten çözmek yerine geçici çözümlerdir. Merak ettiğim bir şey, doğru olanı @ Transactional'ı ilkbahardan ve daha yeni JEE7'den değil kullandınız mı? –

+1

javax one – membersound

+0

kullanıyorum Ve sınıf yolunuzdaki API mı yoksa yalnızca sağlanan bir bağımlılık mı? Ayrıca, arayüz kullanmıyorsunuz, bu yüzden classbased proxy'leri etkinleştirdiğinizden emin olun ... Son olarak postanıza tam stacktrace ekleyebilir misiniz? –

3

Yay Verisi JPA CRUD yöntemini sizin için işlemlerde otomatik olarak çalıştırır (bir işlem yöneticisi dışında bir şey kurmaya gerek kalmadan). Eğer sorgu yöntemleri için işlemleri kullanmak istiyorsanız, sadece bunlara @Transactional ekleyebilirsiniz: Daha genel bir kayda göre

interface MyRepository extends CrudRepository<MyEntity, Integer> { 

    @Transactional 
    @Modifying 
    @Query(value = "TRUNCATE TABLE MyTable", nativeQuery = true) 
    void clear(); 
} 

, burada ne ilan ettiler dışında CrudRepository.deleteAll() mantıksal olarak eşdeğerdir o (senin beyanı) JPA düzeyinde kaskadları onurlandırmıyor. Bu yüzden merak ettim ki gerçekten yapmak istediğin şey bu. Spring Boot kullanıyorsanız, aktivasyon ve işlem yöneticisi kurulumu sizin için yapılmalıdır. Eğer hizmet düzeyine @Transactional kullanmak istiyorsanız

, kurulum ya <tx:annotation-driven /> veya @EnableTransactionManagement (aracılığıyla JpaTransactionManagerve etkinleştirmek açıklama dayalı işlem yönetimini hem ihtiyaç aktivasyon işlemleri oluşturmak için denemede eksik parçası gibi görünüyor Hizmet tabakasında).

+0

@transactional komutunun kullanılması, yayların otomatik olarak işlemlerinizi gerçekleştirir ve temizler. – obesechicken13

+0

Anahtarın ilkbaharda ayarlanmadığından şüpheleniyorum. Temel olarak, Spring sizin için varlık yöneticisini yönetmektedir (bu nedenle kendi işlemlerinizi yönetmenize izin vermez), ancak işlemlerin nasıl yönetileceğini size söylemediniz. –