EJB3映射分离的实体传递给持久化

时间:2013-09-13 15:31:47

标签: java hibernate jpa jboss-arquillian

当我使用Arquillan运行Integrationtesting时,我得到以下错误消息javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist。这可能与我的ID和数据库有关。

以下是它抱怨其域类的类:

@Entity
public class Customer implements IdHolder {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String firstName;
    private String lastName;
    private String email;
    private String company;

    public Customer() {

    }


    public Customer(long id, String firstName, String lastName, String email,
            String company) {
        setId(id);
        setFirstName(firstName);
        setLastName(lastName);
        setEmail(email);
        setCompany(company);

    }

    public long getId() {
        return id;
    }

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

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

}

我还有一个测试工具可以让测试变得更容易,它的实现方式如下:

public class TestFixture {

    private static Logger log = Logger.getLogger(TestFixture.class.getName());

    public static Customer getCustomer(long id, String firstName,
            String lastName, String email, String company) {

        Customer customer = new Customer();
        customer.setId(id);
        customer.setFirstName(firstName);
        customer.setLastName(lastName);
        customer.setEmail(email);
        customer.setCompany(company);

        return customer;

    }

    public static Customer getCustomer() {

        return getCustomer(1, "Darth", "Vader", "skywalker@gmail.com", "Starwars");

    }

    public static Customer getCustomer(String name, String lastName, String email, String company) {

        return getCustomer(0, name, lastName, email, company);

    }

    public static Archive<?> createIntegrationTestArchive() {

        MavenDependencyResolver mvnResolver = DependencyResolvers.use(
                MavenDependencyResolver.class).loadMetadataFromPom("pom.xml");

        WebArchive war = ShrinkWrap.create(WebArchive.class, "agent_test.war")
                .addPackages(true, "se.lowdin")
                .addPackages(true, "se.plushogskolan")
                .addAsWebInfResource("beans.xml")
                .addAsResource("META-INF/persistence.xml");

        war.addAsLibraries(mvnResolver.artifact("org.easymock:easymock:3.2")
                .resolveAsFiles());
        war.addAsLibraries(mvnResolver.artifact("joda-time:joda-time:2.2")
                .resolveAsFiles());
        war.addAsLibraries(mvnResolver.artifact(
                "org.jadira.usertype:usertype.core:3.1.0.CR8").resolveAsFiles());

        log.info("JAR: " + war.toString(true));
        return war;
    }

}

最后,我进行了使用arquillan的集成测试。当我运行测试时,上面的错误即将出现:javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist

@RunWith(Arquillian.class)
@Transactional(TransactionMode.ROLLBACK)
public class JpaCustomerIntegrationTest extends AbstractRepositoryTest<Customer, JpaCustomerRepository> {

    @Inject JpaCustomerRepository repo;

    @Test
    public void testGetAllCustomers() {

        Customer customer1 = TestFixture.getCustomer();
        Customer customer2 = TestFixture.getCustomer();
        customer1.setId(0);
        customer2.setId(0);
        repo.persist(customer1);
        repo.persist(customer2);

        List<Customer> getAllCustomersList = repo.getAllCustomers();
        assertEquals("Check the amount from the list", 2, getAllCustomersList.size());

    }

    @Override
    protected JpaCustomerRepository getRepository() {

        return (JpaCustomerRepository) repo;
    }

    @Override
    protected Customer getEntity1() {

        return TestFixture.getCustomer();
    }

    @Override
    protected Customer getEntity2() {

        return TestFixture.getCustomer();
    }

}

public abstract class JpaRepository<E extends IdHolder> implements BaseRepository<E> {

    /**
     * The JPA type this repository can handle. Only known at runtime. This
     * value is set in the constructor.
     */
    protected Class<E> entityClass;

    @PersistenceContext
    protected EntityManager em;

    @SuppressWarnings("unchecked")
    public JpaRepository() {
        /*
         * A little magic to look into the superclass to find the type we are
         * working on. We use that type in findById() for example .
         */
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
        this.entityClass = (Class<E>) genericSuperclass.getActualTypeArguments()[0];
    }

    @Override
    public long persist(E entity) {
        em.persist(entity);
        return entity.getId();
    }

    @Override
    public void remove(E entity) {
        em.remove(entity);
    }

    @Override
    public E findById(long id) {
        return em.find(entityClass, id);
    }

    @Override
    public void update(E entity) {
        em.merge(entity);
    }

}

当我无法解决这个问题时,我真的觉得自己像个白痴,任何人都可以帮我解释错误吗?

1 个答案:

答案 0 :(得分:0)

您可以将Customer.idlong更改为Long。在持久化实体之前,只需将Id设置为null。这应该有所帮助。