Java Hibernate-SpringMVC-llegal尝试将集合与两个打开的会话相关联
有很多相同类型的问题,但没有一个适合我 我有Spring MVC hibernate应用程序 这是我的两个模型课 Config.javaJava Hibernate-SpringMVC-llegal尝试将集合与两个打开的会话相关联,java,hibernate,spring-mvc,Java,Hibernate,Spring Mvc,有很多相同类型的问题,但没有一个适合我 我有Spring MVC hibernate应用程序 这是我的两个模型课 Config.java public class Config implements java.io.Serializable { private Integer configId; private String configName; private Set<ConfigFields> ConfigFieldses = new HashSet
public class Config implements java.io.Serializable {
private Integer configId;
private String configName;
private Set<ConfigFields> ConfigFieldses = new HashSet<ConfigFields>(0);
//getters and setters
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="configuration")
public Set<ConfigFields> getConfigFieldses() {
return this.ConfigFieldses;
}
public void setConfigFieldses(Set<ConfigFields> ConfigFieldses) {
this.ConfigFieldses = ConfigFieldses;
}
}
public class ConfigFields implements java.io.Serializable {
private Integer configFieldId;
private Confign config;
private String configFieldName;
//getteres and setters
@XmlTransient
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="ConfigId")
public Config getConfig() {
return this.config;
}
public void setConfig(Config configu) {
this.config = config;
}
}
@Repository
@Transactional
public class GenericHibernateDao<T extends Serializable>
implements GenericDao<T>{
@Resource
protected SessionFactory sessionFactory;
@Override
public void insert(T transientInstance) {
sessionFactory.getCurrentSession().persist(transientInstance);
}
@Override
public void update(T instance) {
sessionFactory.getCurrentSession().saveOrUpdate(instance);
}
@Override
public void delete(T persistentInstance) {
sessionFactory.getCurrentSession().delete(persistentInstance);
}
@SuppressWarnings("unchecked")
@Override
public T merge(Serializable detachedInstance) {
return (T) sessionFactory.getCurrentSession().merge(detachedInstance);
}
@SuppressWarnings("unchecked")
@Override
public T findById(Class<?> clazz, Serializable id) {
T t= (T) sessionFactory.openSession().get(clazz, id);
return t;
}
@SuppressWarnings("unchecked")
public List<T> findByNamedQuery(Class<T> clazz, String queryName, Map<String, Object> queryParams) {
Query namedQuery = sessionFactory.getCurrentSession().getNamedQuery(queryName);
for (String s : queryParams.keySet()) {
namedQuery.setParameter(s, queryParams.get(s));
}
return namedQuery.list();
}
}
下面是generichbernatedao.java
public class Config implements java.io.Serializable {
private Integer configId;
private String configName;
private Set<ConfigFields> ConfigFieldses = new HashSet<ConfigFields>(0);
//getters and setters
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="configuration")
public Set<ConfigFields> getConfigFieldses() {
return this.ConfigFieldses;
}
public void setConfigFieldses(Set<ConfigFields> ConfigFieldses) {
this.ConfigFieldses = ConfigFieldses;
}
}
public class ConfigFields implements java.io.Serializable {
private Integer configFieldId;
private Confign config;
private String configFieldName;
//getteres and setters
@XmlTransient
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="ConfigId")
public Config getConfig() {
return this.config;
}
public void setConfig(Config configu) {
this.config = config;
}
}
@Repository
@Transactional
public class GenericHibernateDao<T extends Serializable>
implements GenericDao<T>{
@Resource
protected SessionFactory sessionFactory;
@Override
public void insert(T transientInstance) {
sessionFactory.getCurrentSession().persist(transientInstance);
}
@Override
public void update(T instance) {
sessionFactory.getCurrentSession().saveOrUpdate(instance);
}
@Override
public void delete(T persistentInstance) {
sessionFactory.getCurrentSession().delete(persistentInstance);
}
@SuppressWarnings("unchecked")
@Override
public T merge(Serializable detachedInstance) {
return (T) sessionFactory.getCurrentSession().merge(detachedInstance);
}
@SuppressWarnings("unchecked")
@Override
public T findById(Class<?> clazz, Serializable id) {
T t= (T) sessionFactory.openSession().get(clazz, id);
return t;
}
@SuppressWarnings("unchecked")
public List<T> findByNamedQuery(Class<T> clazz, String queryName, Map<String, Object> queryParams) {
Query namedQuery = sessionFactory.getCurrentSession().getNamedQuery(queryName);
for (String s : queryParams.keySet()) {
namedQuery.setParameter(s, queryParams.get(s));
}
return namedQuery.list();
}
}
我的测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration("classpath:webapptest")
@ContextConfiguration(locations = {"classpath:test-applicationcontext.xml"})
public class ConfigurationsControllerTest {
private MockMvc springMvc;
@Autowired
WebApplicationContext wContext;
@Before
public void init() throws Exception {
springMvc = MockMvcBuilders.webAppContextSetup(wContext).build();
}
@Test
public void deleteConfiguration() throws Exception {
ResultActions resultActions=springMvc.perform(MockMvcRequestBuilders.post("/deleteConfig/117").accept(MediaType.APPLICATION_JSON));
resultActions.andDo(MockMvcResultHandlers.print());
resultActions.andExpect(MockMvcResultMatchers.status().isOk());
}
}
当我在控制台中运行testcase时,logger显示
Illegal attempt to associate a collection with two open sessions
JUnit测试用例stacktrace是
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is bitronix.tm.internal.BitronixRollbackException: transaction was marked as rollback only and has been rolled back
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:932)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:66)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:168)
在Config类中,我有Set,它被设置为CASCADE ALL。因此,我能够在插入配置的同时插入一组配置字段。但现在我想通过传递config对象来删除。所以它应该根据configId从config表中删除1行,从configfields表中删除几行
这里怎么了?如何在不影响应用程序的情况下解决问题(我的意思是插入)您的控制器方法真的像您在这里发布的那样吗?看起来您正在某处检索
config
对象,保留对该对象的引用,然后尝试在后续请求中使用它,您在那里提到的两个变量看起来可能不匹配。您的findById方法有缺陷。永远不要使用openSession()
,而是使用getCurrentSession()
。除了将业务逻辑放在控制器中之外,这实际上属于一种服务方法,该方法将标记为@Transactional
。实际上,注入会话
(或EntityManager
)而不是会话工厂
,通常是一种更安全、更干净的方法。@chrylis-OOps。那是打字错误。我有edited@M.Deinum我有服务课,只有我在打电话。在这个控制器中,我有一些其他事务。所以我把事务性