JPA多对一关系目标实体正在表中保存

时间:2014-01-29 12:49:45

标签: java hibernate jpa orm

我的这个问题是JPA+one-to-many and many-to-one using join table or third table

的后续问题

我引用了Query实体中的Response。当我为Response创建条目时。它还在mydb.tbl_query表中创建了一个条目。我的要求是,当我插入Response实体时,它应该在mydb.tbl_response中插入记录,并通过引用mydb.tbl_map_query_responsequery_id中创建一个条目。

    public class ResponseDAOImplTests extends BaseDAOImplTests {

        @Autowired
        @Qualifier("queryDAO")
        private QueryDAO queryDAO;

        @Autowired
        @Qualifier("responseDAO")
        private ResponseDAO responseDAO;

         /**
         * Query reference.
         */
        private Query query = null;

        /**
         * <p>
         * Adapter for earlier versions of JUnit.
         * </p>
         * 
         * @return a test suite.
         */
        public static junit.framework.Test suite() {
            return new JUnit4TestAdapter(ResponseDAOImplTests.class);
        }

        @Before
        public void setUp() throws QADAOException {
            user = accountDAO.getUser("query2@email.com");
            query = queryDAO.getQuery(2);

        }

        @Test
        public void createResponse() throws QADAOException {
            Response response = new Response();
            response.setQuery(query);
            response.setResponse("ResponseTest1");
            responseDAO.postResponse(response);

        }

    }
public class ResponseDAOImpl extends BasePersitenceDAO implements ResponseDAO {

    @Override
    @Transactional
    public void postResponse(Response response) throws QADAOException {
        getEntityManager().persist(response);
        getEntityManager().flush();

    }
}

public abstract class BasePersitenceDAO {


    @PersistenceContext
    private EntityManager entityManager;
    protected BasePersitenceDAO() {
        // Empty
    }
       protected EntityManager getEntityManager() {
        return entityManager;
    }

       public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}

<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:jee="http://www.springframework.org/schema/jee" xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <context:annotation-config />
    <tx:annotation-driven transaction-manager="transactionManager" />
    <context:component-scan base-package="com.qa" />
    <context:property-placeholder location="classpath:config.properties" />
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="persistenceUnit" />
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <bean id="basePersitenceDAO" abstract="true" class="com.qa.dao.impl.BasePersitenceDAOImpl" />
    <bean id="queryDAO" class="com.qa.dao.impl.QueryDAOImpl" parent="basePersitenceDAO" />
    <bean id="responseDAO" class="com.qa.dao.impl.ResponseDAOImpl" parent="basePersitenceDAO" />
</beans>

我的问题是“它不应该在mydb.tbl_query”中输入另一条记录。

1 个答案:

答案 0 :(得分:1)

Cascade all强制每个JPA操作在引用的实体上级联。在这种情况下,当您在新的Response实体上调用persist时,您有效地在先前读取并在本地缓存的现有分离Query实体上调用persist。它是分离的,因为它之前在不同的上下文中被读取。

查看规范,当在分离的实体上调用persist时,需要持久化以抛出异常。它只是不必立即执行,而是允许插入通过,以便您的数据库应该抛出错误 - 您没有提到它,但我认为这是正在发生的事情。为避免这种情况,您无法在分离的实体上调用persist。

您可以通过多种方式轻松解决此问题 1)在您的Response - &gt;查询关系中不使用级联持久性。级联都包括级联持久性,因此您只需添加模型所需的级联。我强烈建议你看看级联是什么意思,无论如何都要谨慎使用它 2)在持久响应的相同上下文中查找查询。您的响应DAO可以轻松获取查询ID和字符串值并为您创建一个Response对象 - 使用Id执行查询查询。
3)使用merge代替。 Merge将创建新的Response,但会将分离的Query实例合并到它查找的托管副本中。但这有风险,因为对Query对象所做的任何更改都将合并并使用Response插入放入数据库中。因此,您的ResponseDAO不仅仅是响应更改。