测试jpa实体类 - 错误需要事务 [英] Testing jpa entity classes - error Transaction is required

查看:84
本文介绍了测试jpa实体类 - 错误需要事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于原型我创建了一个java ee应用程序。有一个包括arquillian测试运行正常。它只是在@Stateless bean上调用一个持久化预制实体的方法。

Based on an archetype i created a java ee app. There is an included arquillian test that runs fine. it just calls a method on a @Stateless bean that persists an pre-made entity.

现在我添加了一些具有某种关系的实体,我为它们编写了一个测试。但是在持有任何实体时我得到了

now i added some entity with some relations and i wrote a test for them. But on peristing any entity i get

Transaction is required to perform this operation (either use a transaction or extended persistence context)

我想我需要用@Transactional标记testmethod,但似乎不是在类路径中。
在注入的EntityManager上手动调用事务会产生另一个错误。
所以如何正确设置这样的测试和依赖关系。

I think i need to mark the testmethod with @Transactional but it seems not to be in class path. Manually invoking the transaction on injected EntityManager yields another error. So how to correctly setup such tests and dependencies.

编辑正如Grzesiek D.在此提出的一些细节。这是实体(一个链接其他实体):

EDIT As Grzesiek D. suggested here are some details. this is the entity (the one thta links others):

@Entity
public class Booking implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    /**
     * internal id.
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;
    /**
     * Used for optimistic locking.
     */
    @Version
    @Column(name = "version")
    private int version;

    /**
     * A booking must have a project related.
     */
    @ManyToOne
    @JoinColumn(name = "project_id")
    @NotNull
    private Project project;

    /**
     * A booking must have an owner.
     */
    @ManyToOne
    @JoinColumn(name = "user_id")
    @NotNull
    private User owner;

    /**
     * A booking always has a start time.
     */
    @Column
    @NotNull
    private Timestamp start;

    /**
     * A booking always has an end time.
     */
    @Column
    @NotNull
    private Timestamp end;

    /**
     * 
     * @return true if start is befor end. false otherwise (if equal or after end).
     */
    @AssertTrue(message = "Start must before end.")
    public final boolean isStartBeforeEnd() {
        return start.compareTo(end) < 0;
    }

    /**
     * @return the id
     */
    public final Long getId() {
        return id;
    }

    /**
     * @param id
     *            the id to set
     */
    public final void setId(final Long id) {
        this.id = id;
    }

    /**
     * @return the version
     */
    public final int getVersion() {
        return version;
    }

    /**
     * @param version
     *            the version to set
     */
    public final void setVersion(final int version) {
        this.version = version;
    }

    /**
     * @return the project
     */
    public final Project getProject() {
        return project;
    }

    /**
     * @param project
     *            the project to set
     */
    public final void setProject(final Project project) {
        this.project = project;
    }

    /**
     * @return the owner
     */
    public final User getOwner() {
        return owner;
    }

    /**
     * @param owner
     *            the owner to set
     */
    public final void setOwner(final User owner) {
        this.owner = owner;
    }

    /**
     * @return the start
     */
    public final Timestamp getStart() {
        return start;
    }

    /**
     * @param start
     *            the start to set
     */
    public final void setStart(final Timestamp start) {
        this.start = start;
    }

    /**
     * @return the end
     */
    public final Timestamp getEnd() {
        return end;
    }

    /**
     * @param end
     *            the end to set
     */
    public final void setEnd(final Timestamp end) {
        this.end = end;
    }

    //hashCode, equals, toString omitted here
}

以下是测试:

@RunWith(Arquillian.class)
public class BookingTest {

    @Deployment
    public static Archive<?> createDeployment() {
        return ArquillianContainer.addClasses(Resources.class, Booking.class, Project.class, User.class);
    }

    @Inject
    private EntityManager em;

    @Test
    public void createBooking() {
        Booking booking = new Booking();
        booking.setStart(new Timestamp(0));
        booking.setEnd(new Timestamp(2));
        User user = new User();
        user.setName("Klaus");
        booking.setOwner(user);
        Project project = new Project();
        project.setName("theOne");
        project.setDescription("blub");
        booking.setProject(project);
        em.persist(booking);
        System.out.println("here");
    }

}

此处例外:

javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)

我知道如果我创建一个@Stateless bean并封装那里的persist但它我会想要直接测试实体的验证,我需要一个游乐场来改进数据模型。

I know it will work if i create a @Stateless bean and encapsulate the persist there but i want a direct test of entity's validation and i need a playground to evolve the data model.

推荐答案

为了在Arquillian测试中获得交易支持,你需要引入启用此功能的扩展程序。在你的情况下 jta 依赖应该完成这项工作。

In order to have transaction support in Arquillian tests you will need to bring in extension which enables this feature. In your case jta dependency should do the job.

<dependency>
  <groupId>org.jboss.arquillian.extension</groupId>
  <artifactId>arquillian-transaction-jta</artifactId>
  <scope>test</scope>
</dependency>

此外,如果您使用JBoss,则需要为 UserTranscation 提供其JNDI,因此请在 arquillian.xml中添加以下部分

In addition, if you are using JBoss, you will need to provide its JNDI for UserTranscation, so put following section in your arquillian.xml:

<?xml version="1.0" ?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://jboss.org/schema/arquillian" xsi:schemaLocation="http://jboss.org/schema/arquillian
    http://jboss.org/schema/arquillian/arquillian_1_0.xsd">     

  <extension qualifier="transaction">
    <property name="manager">java:jboss/UserTransaction</property>
  </extension>

</arquillian>

这样你就可以使用 @Transactional 来自此扩展程序的API。

This way you can use @Transactional which comes from this extension's API.

这篇关于测试jpa实体类 - 错误需要事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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