簡體   English   中英

Spring3 JPA(Hibernate4)沒有持久化

[英]Spring3 JPA (Hibernate4) not persisting

我有一個使用Spring 3.2.3和Hibernate 4.2.1.Final的應用程序。 我做了一些配置,應用程序在測試環境中運行得非常好,使用HSQLDB等。

但是當部署應用程序時,它幾乎可以正常工作。 實體已創建但從未保留。 我可以看到JPA日志:

Hibernate:選擇nextval('TASK_SEQ')

但是插件永遠不會出現=(

使用配置:

 <?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> 

實體:

@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
}

最后服務:

@Service
public class TaskService {

    @PersistenceContext
    private EntityManager entityManager;

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

正如我所說,沒有異常被拋出,但實體並沒有像測試那樣持久存在。 謝謝!

編輯:我還嘗試將persistence.xml內容刪除到spring數據源中,問題仍然是相同的:

<?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>

解:

我放棄了xml配置。 似乎沒有任何東西可以用它了。 閱讀更多有關趨勢和大量配置的信息,我最終成功嘗試了java配置並進行了一些調整,這非常適合。 見下文:

    @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();
        }
    }

首先,您應該啟用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應位於該包下。

編輯

您應該將@Transactional用於實現interface public方法。 默認情況下,Spring通過簡單的Java Proxy實現通知注釋,這需要一個接口。

第8.1.3節AOP代理中所述

Spring AOP默認使用AOP代理的標准J2SE動態代理。 這使得任何接口(或接口集)都可以被代理。

當然,這也意味着TaskService應該僅通過該接口由其他bean引用。

我遇到了類似於描述的問題。 我發現@Transactional表示法的使用不正確的問題,特別是我錯誤地使用了javax.transaction.Transactional而不是org.springframework.transaction.annotation.Transactional

看一下“@Service”的導入。

有關差異的詳細說明,請參見javax.transaction.Transactional vs org.springframework.transaction.annotation.Transactional

由於TaskService被定義為服務,因此Spring容器不會維護CRUD操作的事務。 您應該將CRUD操作委托給另一個bean - 通常我將它們與Managers后綴。

這將是事務工作流的完整層次結構:

  1. 創建一個普通的bean。 我們說TaskManager
  2. 將新創建的類注入TaskService

@Resource(name =“taskManager”)

TaskManager taskManager;

3。 在新創建的Manager類中注入EntityManager

4。 將所有CRUD方法放在manager類中

5。 從Service調用這些方法

呼叫層次結構:服務 - >管理器 - > DAO - >實體管理器

現在你應該能夠堅持你的實體了。

我首先要仔細檢查一些明顯的東西:Task類型是br.com.company.Task,而不是其他java api任務?

如果您仍然遇到同樣的問題,那么您的交易管理可能出現問題。 保持后嘗試刷新entityManager。 通常,entityManager應在事務結束時自動刷新:

@Transactional(propagation = Propagation.REQUIRED)
public void createTask(Task task) {
  entityManager.persist(task);
  entityManager.flush(task);
}

如果您確實遇到了事務管理器的問題,請嘗試而不是在persistence.xml中指定數據源,在spring xml上創建它並使用JpaTransactionManager的dataSource屬性

還可以在log4j logger之后設置以查看hibernate發出的事務開始/結束和SQL:

log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.transaction=DEBUG

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM