我的这个问题是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_response
在query_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
”中输入另一条记录。
答案 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不仅仅是响应更改。