1

Spring 3.2.3 と Hibernate 4.2.1.Final を使用するアプリケーションがあります。いくつかの設定を行ったところ、アプリは HSQLDB などを使用してテスト環境でうまく動作します。

しかし、アプリが展開されると、ほとんど問題なく動作します。エンティティは作成されますが、永続化されません。JPA ログを確認できます。

休止状態: 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 コンテンツを春のデータソースに削除しようとしましたが、問題は同じです:

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

4 に答える 4

2

まず、次のようにPersistenceAnnotationBeanPostProcessorBeanを有効にする必要があります。

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

Spring 3.1.x doc のセクション 14.5.2 に記載されているとおり:

PersistenceAnnotationBeanPostProcessor が有効になっている場合、Spring は @PersistenceUnit および @PersistenceContext アノテーションをフィールド レベルとメソッド レベルの両方で理解できます。

もう1つ、TaskServiceスキャンされていることを確認してください。投稿された Spring 構成ファイルによると、パッケージのみbr.com.companyがスキャンされるためTaskService、そのパッケージの下にあるはずです。

編集

@Transactionalを実装するpublicメソッドに使用する必要がありますinterface。デフォルトでは、アドバイス アノテーションはインターフェースを必要とする単純な JavaProxyを介して Spring によって実装されます。

セクション 8.1.3 AOP Proxiesに記載されているとおり:

Spring AOP はデフォルトで、AOP プロキシに標準の J2SE 動的プロキシを使用します。これにより、任意のインターフェイス (または一連のインターフェイス) をプロキシできるようになります。

もちろん、これは、TaskServiceそのインターフェースのみを介して他の Bean によって参照される必要があることも意味します。

于 2013-07-14T23:16:37.330 に答える
1

説明されている問題に似た問題に直面しました。@Transactional 表記の不適切な使用に問題があることがわかりました。特に、org.springframework.transaction.annotation.Transactional の代わりに javax.transaction.Transactional を誤って使用しました。

「@Service」のインポートを見てください。

違いの詳細な説明は、javax.transaction.Transactional と org.springframework.transaction.annotation.Transactionalにあります。

于 2015-01-12T23:56:46.247 に答える
0

最初にいくつかの明白なことを再確認します: Task タイプは br.com.company.Task であり、他の Java api Task ではありませんでしたか?

それでも同じ問題が発生する場合は、トランザクション管理に何か問題がある可能性があります。永続化した後、entityManager をフラッシュしてみてください。通常、entityManager はトランザクションの最後に自動的にフラッシュする必要があります。

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

トランザクションマネージャーに問題がある場合は、persistence.xml 内でデータソースを指定する代わりに、Spring xml で作成し、JpaTransactionManager の dataSource プロパティを使用してみてください

また、次の log4j ロガーを設定して、トランザクションの開始/終了と、休止状態によって発行された SQL を確認します。

log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.transaction=DEBUG
于 2013-07-14T23:05:49.800 に答える
0

サービスとしてTaskService定義されているため、Spring コンテナーは CRUD 操作のトランザクションを維持しません。CRUD 操作を別の Bean に委譲する必要があります。通常は、マネージャーに接尾辞を付けます。

したがって、これはトランザクション ワークフローの完全な階層になります。

  1. 通常の Bean を作成します。まあ言ってみればTaskManager
  2. 新しく作成したクラスを TaskService に挿入する

@Resource(name = "タスクマネージャー")

タスクマネージャータスクマネージャー;

  3. EntityManager新しく作成した Manager クラスに etc を注入する

  4 . すべての CRUD メソッドをマネージャー クラスに入れる

  5. これらのメソッドを Service から呼び出す

呼び出し階層: Service -> Manager -> DAO -> Entity Manager

これで、エンティティを永続化できるはずです。

于 2013-07-14T20:55:38.820 に答える