Spring3 JPA(Hibernate4)不会持久 [英] Spring3 JPA (Hibernate4) not persisting

查看:99
本文介绍了Spring3 JPA(Hibernate4)不会持久的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Spring 3.2.3和Hibernate 4.2.1.Final的应用程序。
我做了一些配置,使用HSQLDB等应用程序在测试环境中工作得很好。



但是当应用程序部署时,它几乎可以正常工作。该实体已创建但从未持久。
我可以看到JPA日志:

Hibernate:
select
nextval('TASK_SEQ')



但插入从不出现=($ / b>
$ b

使用配置:

<$ p $ >
< beans xmlns =http://www.springframework.org/schema/beans xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xmlns:context =http://www.springframework.org/schema/contextxmlns:tx = http://www.springframework.org/schema/tx
xmlns:p =http://www.springframework.org/schema/pxmlns:aop =http://www.springframework。 org / schema / aop
xsi:schemaLocation =http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans- 3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http ://www.springframework.org/schema/tx
http://www.springframewor k.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/弹簧AOP-3.2.xsd>

< context:component-scan base-package =br.com.company/>

< bean id =entityManagerFactoryclass =org.springframework.orm.jpa.LocalEntityManagerFactoryBean>
< property name =persistenceUnitNamevalue =spring_pu/>
< / bean>

< bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager>
< property name =entityManagerFactoryref =entityManagerFactory/>
< / bean>

< context:annotation-config />
< tx:注解驱动的事务管理器=transactionManager/>

< bean class =org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor/>

< / beans>

persistence.xml

 <?xml version =1.0encoding =UTF-8?> 
< persistence xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation =http://java.sun.com/xml/ns / persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd
version =2.0xmlns =http://java.sun.com/xml/ns/persistence >
< persistence-unit name =spring_putransaction-type =RESOURCE_LOCAL>
< provider> org.hibernate.ejb.HibernatePersistence< / provider>
< class> br.com.company.core.entities.Task< / class>
<属性>
< property name =hibernate.connection.autocommitvalue =true/>
< property name =hibernate.show_sqlvalue =true/>
< property name =hibernate.format_sqlvalue =true/>
< property name =hibernate.dialectvalue =org.hibernate.dialect.PostgreSQLDialect/>
< property name =hibernate.hbm2ddl.autovalue =update/>

< property name =hibernate.connection.driver_classvalue =org.postgresql.Driver/>
< property name =hibernate.connection.urlvalue =jdbc:postgresql://127.0.0.1:5432 / companyDB/>
< property name =hibernate.connection.uservalue =postgres/>
< property name =hibernate.connection.passwordvalue =*****/>
< / properties>
< / persistence-unit>
< /余辉>

实体:

  @Entity 
@Table(name =TASK)
public class Task实现Serializable {

private static final long serialVersionUID = -6262731134419520342L;

@Id
@Column(name =ID)
@GeneratedValue(generator =TASK_SEQ,strategy = GenerationType.SEQUENCE)
@SequenceGenerator(sequenceName =TASK_SEQ,name =TASK_SEQ)
私人长ID;

@Column(name =DESCRIPTION)
私有字符串描述;

@Column(name =FINISHED)
private boolean fininshed;

@Temporal(TemporalType.TIMESTAMP)
@Column(name =FINISH_DATE)
私人日期finishDate;

// getters and setter below
}

最后服务:

  @Service 
public class TaskService {

@PersistenceContext
私人EntityManager entityManager;

@Transactional(propagation = Propagation.REQUIRED)
public void createTask(Task task){
< b> //被调用的方法< / b>
entityManager.persist(task);





$ b正如我所说的,没有例外被抛出,但实体并没有被持久化就像它在测试中一样。
谢谢!



编辑:我也尝试将persistence.xml内容移除到一个spring数据源中,问题依然如此:

 <?xml version =1.0encoding =UTF-8?> 
< beans xmlns =http://www.springframework.org/schema/beansxmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xmlns :context =http://www.springframework.org/schema/contextxmlns:tx =http://www.springframework.org/schema/tx
xmlns:p =http:// www.springframework.org/schema/pxmlns:aop =http://www.springframework.org/schema/aop
xsi:schemaLocation =http://www.springframework.org/schema/ beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http:/ /www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema /tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2的.xsd>

< bean class =org.springframework.jdbc.datasource.DriverManagerDataSourceid =dataSource>
< property name =driverClassNamevalue =org.postgresql.Driver/>
< property name =urlvalue =jdbc:postgresql://127.0.0.1:5432 / KCILDS/>
< property name =usernamevalue =postgres/>
< property name =passwordvalue =*****/>
< / bean>

< context:component-scan base-package =br.com.company/>

< bean id =myEntityManagerFactoryclass =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =dataSourceref =dataSource/>
< property name =packagesToScanvalue =br.com.company.core.entities/>
< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter/>
< / property>
< property name =jpaProperties>
<道具>
< prop key =hibernate.hbm2ddl.auto> update< / prop>
< prop key =hibernate.dialect> org.hibernate.dialect.PostgreSQLDialect< / prop>
< prop key =hibernate.show_sql> true< / prop>
< prop key =hibernate.format_sql> true< / prop>
< /道具>
< / property>
< / bean>

< bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager>
< property name =entityManagerFactoryref =myEntityManagerFactory/>
< / bean>

< context:annotation-config />
< tx:注解驱动的事务管理器=transactionManager/>

< bean class =org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor/>

< / beans>

解决方案:

我放弃了xml配置。似乎没有任何工作。
阅读更多关于趋势和很多配置我最终成功尝试了一个java配置并进行了一些更多的调整,完全适合。
见下:

  @Configuration 
@EnableTransactionManagement
@ComponentScan(br.com ()公共类)
public class PersistenceJPAConfig {

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(this.directDataSource());
factoryBean.setPackagesToScan(new String [] {br.com.company});

HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);

factoryBean.setJpaVendorAdapter(vendorAdapter);
factoryBean.setJpaProperties(this.additionlProperties());

返回factoryBean;


私有属性additionlProperties(){
属性properties = new Properties();
properties.put(database,POSTGRESQL);
properties.put(databasePlatform,org.hibernate.dialect.PostgreSQLDialect);
properties.put(Environment.SHOW_SQL,true);
properties.put(Environment.FORMAT_SQL,true);
返回属性;
}

//现在研究如何使它成为一个环境配置
// @Bean
// public DataSource dataSource(){
// JndiDataSourceLookup jndiDataSourceLookup = new JndiDataSourceLookup();
// jndiDataSourceLookup.setResourceRef(true);
// return jndiDataSourceLookup.getDataSource(jdbc / mybank);
//

@Bean
public DataSource directDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(org.postgresql.Driver);
dataSource.setUrl(jdbc:postgresql://127.0.0.1:5432 / MyBank);
dataSource.setUsername(postgres);
dataSource.setPassword(*******);
返回dataSource;

$ b $ @Bean //仍然尝试创建JTA事务$ b $ public PlatformTransactionManager transactionManager(){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(this.entityManagerFactoryBean()。getObject());
返回transactionManager;


@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
}


解决方案

,您应该启用 PersistenceAnnotationBeanPostProcessor bean,如下所示:

 < bean class =org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor/> 

Spring 3.1.x doc,第14.5.2节


如果启用了
PersistenceAnnotationBeanPostProcessor,Spring可以在字段和方法级别理解@PersistenceUnit和@PersistenceContext
注释。


另一件事,确保您的 TaskService 被扫描。根据发布的Spring配置文件,只扫描 br.com.company 包,因此 TaskService 应该在
$ b

编辑



您应该使用 @对于实现接口 public 方法,Transactional 。默认情况下,建议注释由Spring通过简单Java 代理 ,它需要一个接口。 第8.1.3节AOP代理 :


Spring AOP默认使用标准的J2SE动态代理来处理AOP
代理。这使得任何接口(或一组接口)都可以被代理


当然,这也意味着 TaskService 应该由其他bean单独通过该接口引用。


I have an application using Spring 3.2.3 and Hibernate 4.2.1.Final. I made some configurations and the app works pretty well on the test environment, using HSQLDB, etc.

But when the app is deployed it almost works fine. The entity is created but never persisted. I can see the JPA logs:

Hibernate: select nextval ('TASK_SEQ')

But an insert never appears =(

Using the configuration:

 <?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd  
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <context:component-scan base-package="br.com.company" />

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="spring_pu" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <context:annotation-config />
    <tx:annotation-driven transaction-manager="transactionManager" />

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

</beans>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="spring_pu" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>br.com.company.core.entities.Task</class>
        <properties>
                <property name="hibernate.connection.autocommit" value="true" />
        <property name="hibernate.show_sql" value="true" />
        <property name="hibernate.format_sql" value="true" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
        <property name="hibernate.hbm2ddl.auto" value="update" />

            <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
            <property name="hibernate.connection.url" value="jdbc:postgresql://127.0.0.1:5432/companyDB" />
            <property name="hibernate.connection.user" value="postgres" />
            <property name="hibernate.connection.password" value="*****" />
        </properties>
    </persistence-unit>
</persistence> 

The entity:

@Entity
@Table(name = "TASK")
public class Task implements Serializable {

    private static final long serialVersionUID = -6262731134419520342L;

    @Id
    @Column(name = "ID")
    @GeneratedValue(generator = "TASK_SEQ", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(sequenceName = "TASK_SEQ", name = "TASK_SEQ")
    private long id;

    @Column(name = "DESCRIPTION")
    private String description;

    @Column(name = "FINISHED")
    private boolean fininshed;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "FINISH_DATE")
    private Date finishDate;

//getters and setter below
}

And finally the service:

@Service
public class TaskService {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional(propagation = Propagation.REQUIRED)
    public void createTask(Task task) {
    <b>//invoked method</b>
        entityManager.persist(task);
    }

As I said, there are no exceptions being thrown but the entity is not persisted like it is at the tests. Thank you!

Edit: I also tried to remove the persistence.xml content into a spring datasource and the problem is still the same:

<?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd  
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://127.0.0.1:5432/KCILDS" />
        <property name="username" value="postgres" />
        <property name="password" value="*****" />
    </bean>

    <context:component-scan base-package="br.com.company" />

    <bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="br.com.company.core.entities" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="myEntityManagerFactory" />
    </bean>

    <context:annotation-config />
    <tx:annotation-driven transaction-manager="transactionManager" />

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

</beans>

SOLUTION:

I give up the xml configuration. Nothing seems to work with it anymore. Reading more about the tendencies and a lot of configuration I ended up trying successfully a java config and with a few more adjustments will fit perfectly. See below:

    @Configuration
    @EnableTransactionManagement
    @ComponentScan("br.com.company")
    public class PersistenceJPAConfig {

        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
            LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
            factoryBean.setDataSource(this.directDataSource());
            factoryBean.setPackagesToScan(new String[] { "br.com.company" });

            HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            vendorAdapter.setShowSql(true);

            factoryBean.setJpaVendorAdapter(vendorAdapter);
            factoryBean.setJpaProperties(this.additionlProperties());

            return factoryBean;
        }

        private Properties additionlProperties() {
            Properties properties = new Properties();
            properties.put("database", "POSTGRESQL");
            properties.put("databasePlatform", "org.hibernate.dialect.PostgreSQLDialect");
            properties.put(Environment.SHOW_SQL, true);
            properties.put(Environment.FORMAT_SQL, true);
            return properties;
        }

// now reasearch how to make it an environment configuration
    //  @Bean
    //  public DataSource dataSource() {
    //      JndiDataSourceLookup jndiDataSourceLookup = new JndiDataSourceLookup();
    //      jndiDataSourceLookup.setResourceRef(true);
    //      return jndiDataSourceLookup.getDataSource("jdbc/mybank");
    //  }

        @Bean
        public DataSource directDataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName("org.postgresql.Driver");
            dataSource.setUrl("jdbc:postgresql://127.0.0.1:5432/MyBank");
            dataSource.setUsername("postgres");
            dataSource.setPassword("*******");
            return dataSource;
        }

        @Bean //still trying to make a JTA Transaction
        public PlatformTransactionManager transactionManager() {
            JpaTransactionManager transactionManager = new JpaTransactionManager();
            transactionManager.setEntityManagerFactory(this.entityManagerFactoryBean().getObject());
            return transactionManager;
        }

        @Bean
        public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
            return new PersistenceExceptionTranslationPostProcessor();
        }
    }

解决方案

First, you should enable a PersistenceAnnotationBeanPostProcessor bean, like so:

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

As documented in Spring 3.1.x doc, section 14.5.2:

Spring can understand @PersistenceUnit and @PersistenceContext annotations both at field and method level if a PersistenceAnnotationBeanPostProcessor is enabled.

Another thing, make sure your TaskService is scanned. According to the posted Spring configuration file, only the package br.com.company is scanned so TaskService should be under that package.

EDIT

You should use @Transactional for public methods that implement an interface. By default, advice annotation are implemented by Spring via simple Java Proxy, which requires an interface.

As documented in section 8.1.3 AOP Proxies:

Spring AOP defaults to using standard J2SE dynamic proxies for AOP proxies. This enables any interface (or set of interfaces) to be proxied.

Of course, this also implies that TaskService should be referenced by other beans via that interface alone.

这篇关于Spring3 JPA(Hibernate4)不会持久的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆