2015-09-14 8 views
11

Sto utilizzando JPA nella mia applicazione e funziona una volta che eseguo query per gli oggetti, tuttavia viene generato l'errore javax.persistence.TransactionRequiredException: No transactional EntityManager available dopo aver provato a salvare o aggiornare un oggetto.Impossibile salvare/aggiornare l'entità utilizzando JPA in primavera

Questa è la configurazione di Java:

@Configuration 
@EnableTransactionManagement(proxyTargetClass = true) 
@PropertySource("classpath:dao.properties") 
public class JpaConfig { 
    @Autowired 
    private Environment env; 
    @Bean 
    public DataSource dataSource() { 
     BasicDataSource dataSource = new BasicDataSource(); 
     ..................... 
     return dataSource; 
    } 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
     Properties jpaProperties = new Properties(); 
     jpaProperties.put("hibernate.dialect", ...........) 

     LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 
     entityManagerFactoryBean.setDataSource(dataSource()); 
     entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
     entityManagerFactoryBean.setJpaProperties(jpaProperties); 
     entityManagerFactoryBean.setPackagesToScan("com...."); 
     return entityManagerFactoryBean; 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(emf); 
     return transactionManager; 
    } 
} 

Nota che uso proxyTargetClass = true nel @EnableTransactionManagement, dato che non voglio creare le interfacce inutili nella mia applicazione.

E questa è la fine dell'esecuzione concreta del dao:

@Transactional 
@Repository 
public abstract class AbstractJPADao<I, E> { 
    @Autowired 
    @PersistenceContext 
    protected EntityManager entityManager; 

    private Class<E> type; 
    public AbstractJPADao() { 
     type=.... 
    } 

    @Override 
    public Result<E> find(I id) { 
     E e = entityManager.find(type, id); 
     return Result.newInstance().setContent(e); 
    } 

    @Override 
    public Result<E> find(Map<String, Object> condition) { 
     Query q = entityManager.createQuery(".......)); 
     return Result.newInstance().setContent(q.getResultList()); 
    } 

    @Override 
    public E save(E element) { 
     entityManager.persist(element); 
     return element; 
    } 
    @Override 
    public E update(E element) { 
     entityManager.merge(element); 
     return element; 
    } 

    @Override 
    public void delete(E element) { 
     entityManager.remove(element); 
    } 
} 

@Repository 
@Transactional 
public class DepartmentDao extends AbstractJPADao<String, Department> { 
    @Override 
    protected String selectCause(Map<String, Object> condition) { 
     return ""; 
    } 
} 

E il controller come il client del dao:

@Controller 
@RequestMapping("/api/deps") 
public class DepartmentCtrl { 
    @Autowired 
    private DepartmentDao departmentDao; 
    @RequestMapping(value = "", method = RequestMethod.POST) 
    public Result create(@Valid Department department, BindingResult bindingResult) { 
     if (!bindingResult.hasErrors()) { 
      departmentDao.save(department); 
      return Result.newInstance().setContent(department); 
     } 
     throw new RuntimeException("..."); 
    } 
} 

qualcosa che non va?


dao.properties:

jdbc.driverClassName=com.mysql.jdbc.Driver 
jdbc.url=jdbc:mysql://localhost:3306/proj 
jdbc.username=root 
jdbc.password= 

hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 
hibernate.hbm2ddl.auto=update 
#hibernate.ejb.naming_strategy=true 
hibernate.show_sql=true 
hibernate.format_sql=true 
+1

Perché ci sono due annotazioni '@ Autowired' e' @ PersistenceContext' sul campo 'protected' di tipo' EntityManager' in 'AbstractJPADao'? – Tiny

+0

'EntityManager' è fornito in' JpaConfig' come bean che deve essere iniettato in 'AbstractJPADao'. – hguser

+0

In quale contenitore stai correndo? –

risposta

4

provare il metodo transactionManager rinominando txManager nella classe JpaConfig

autowiring va sotto il nome txManager

Modifica

Inoltre il framework potrebbe prevedere un metodo senza argomenti per txManager. Si può provare a cambiare per

@Bean 
public PlatformTransactionManager transactionManager() { 
    JpaTransactionManager transactionManager = new JpaTransactionManager(); 
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); 
    return transactionManager; 
} 
+0

Non funziona. – hguser

+0

@hguser Modificato la mia risposta. Potresti provare per favore? – gipsy

+0

Grazie, ho provato: rimuovere gli argomenti nel metodo e utilizzare sia 'transactionManager' che 'txManager' come nome del metodo. Nessuno di loro funziona. :( – hguser

1

Come notato piccolo, avete due annotazioni @Autowired e @PersistenceContext sopra il campo di tipo EntityManager in AbstractJPADao protetta. Prova a rimuovere @Autowired. @PersistenceContext è sufficiente per iniettare EntityManager.

+0

Non risolve questo problema. – hguser

Problemi correlati