0

我之前使用过 Java EE 6,我在服务器上创建了一个连接资源(池化),然后将其绑定到我jta-data-source在 Persistence.xml 文件的元素标记中引用的 JNDI 名称。

现在我使用 Spring 3,我很难理解我需要设置的所有不同 bean 以及为什么需要这样做。EJB 3 自动将方法包装在事务中。在 Spring 中,您似乎需要配置事务管理器,但我不知道。需要解释。

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myapp" expected-type="javax.sql.DataSource"/>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
    <property name="packagesToScan" value="com.myapp.app"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">
                org.hibernate.dialect.PostgreSQL82Dialect
            </prop>
        </props>
    </property>
</bean>

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

<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />

我了解数据源的 jndi 查找,但是我不了解其余部分。我无法使用此配置插入/保留对象。

我需要解释一下 Spring 3 在这方面与 Java EE 6 有何不同,以及如何以同样的方式做到这一点。

4

1 回答 1

2

在对您的原始问题进行了更多思考之后,我想补充一下:

Spring 不会自动用 Transaction 包装每个方法。你必须告诉 Spring 你希望你的事务边界在哪里。您可以使用 XML 配置或使用 @Transactional 注释来执行此操作。

你应该看看你应该在哪里声明交易——这里这里

你应该看看 Spring 的事务管理 -这里

你应该看看 Transaction Config - here

我仍然认为您的配置很好,并且您遇到的问题在于尝试使用您的 EntityManager 的 bean。我再次请求你发布它,因为我确信如果我能看到它,我可以让你去。


我查看了您的配置,但没有发现任何问题。作为一个例子,我将(在底部)提供我现在在一个工作应用程序中的一些东西。

我不相信您的问题出在您的配置中,而在于您对已配置 bean 的使用。如果您可以提供向我(我们)展示您如何与 EntityManager 交互的代码,我可能会发现您的问题。

我将为您提供实体、存储库和 XML 配置的工作示例,以尝试帮助您找到问题:

弹簧配置(applicationContext.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:p="http://www.springframework.org/schema/p"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                           http://www.springframework.org/schema/jee     http://www.springframework.org/schema/jee/spring-jee.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">
    <context:annotation-config />

    <context:component-scan base-package="com.company.app.dao" />
    <context:component-scan base-package="com.company.app.service" />

    <jee:jndi-lookup id="dataSource"
                     jndi-name="jdbc/Test" />

    <bean id="jpaDialect"
          class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />

    <bean id="jpaAdapter"
          class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />

    <bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource"       ref="dataSource" />
        <property name="jpaVendorAdapter" ref="jpaAdapter" />
        <property name="jpaDialect"       ref="jpaDialect" />
        <property name="packagesToScan" value="com.company.app.model" />
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager"
          class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManager" />

    <tx:annotation-driven transaction-manager="transactionManager"
                          proxy-target-class="true" />
</beans>

模型

import org.hibernate.validator.constraints.Length;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

@Entity
public class User {
    @Id
    private String id = UUID.randomUUID().toString();

    @Column
    @Length(min = 3, max = 25)
    private String name;

    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name = "userId", nullable = false)
    private Set<Contact> contacts = new HashSet<Contact>();

    public UUID getId() {
        return UUID.fromString(id);
    }

    public void setId(UUID id) {
        this.id = id.toString();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Contact> getContacts() {
        return contacts;
    }

    public void setContacts(Set<Contact> contacts) {
        this.contacts = contacts;
    }

    public void addContact(Contact contact) {
        this.contacts.add(contact);
    }

    public void removeContact(Contact contact) {
        this.contacts.remove(contact);
    }
}

存储库

import com.company.app.model.User;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaQuery;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

@Repository
public class UserDao {
    @PersistenceContext
    private EntityManager em;

    @Transactional(propagation = Propagation.REQUIRED)
    public void createUser(User user) {
        em.persist(user);
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
    public User readUserById(UUID id) {
        CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
        query.where (em.getCriteriaBuilder().equal(query.from(User.class).get("id"),id.toString()));
        return em.createQuery(query).getSingleResult();
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
    public Set<User> readAll() {
        CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
        query.from(User.class);
        return new HashSet<User>(em.createQuery(query).getResultList());
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public User update(User user) {
        return em.merge(user);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void delete(User user) {
        em.remove(user);
    }
}
于 2013-04-19T15:40:48.617 回答