我有这个问题:
我用实体准备视图
@RequestMapping("/admin/modifyImplant/{id}")
public ModelAndView modifyImplant(@PathVariable Integer id) {
ModelAndView mav = new ModelAndView();
Implant currentImplant =impDAO.findById(id); //this is the dao
Implanttype it= currentImplant.getImplanttype();
Implantinverter ii=new Implantinverter();
ArrayList<Implantpanel> implantpanels = new ArrayList<Implantpanel>();
try{
ii= (Implantinverter)currentImplant.getImplantinverters().toArray()[0];
implantpanels=(ArrayList<Implantpanel>) imppanelDAO.findByProperty("implant",currentImplant );
}
catch (Exception ex){
//TODO
}
mav.addObject("implantpanels", implantpanels);
mav.addObject("implantinverter",ii);
mav.addObject("implant", currentImplant); //THIS IS THE ENTITY I MEAN
mav.addObject("implanttype",it);
mav.setViewName("/implant/modifyImplant.jsp");
return mav;
}
这个代码接近jsp(代码的一小部分)
<form:form action="${pageContext.request.contextPath}/admin/finalizeModifyImplant/${implant.id}" method="POST" modelAttribute="implant">
<table cellpadding="0" cellspacing="0" id="viewTable" >
<tbody>
<tr>
<td class="label">
Name:
</td>
<td>
<form:input id="User_namesurname" path="businessname" cssStyle="width:300px;"/>
</td>
</tr>
以及实体领域等等。 该实体有一些相关的实体,通过外键连接(如种植体,植入反射器,种植体)。
提交给该控制器:
@RequestMapping(value = "/admin/finalizeModifyImplant/{id}",
method = { RequestMethod.GET,RequestMethod.POST })
public ModelAndView finalizeModifyImplant(@PathVariable int id, @Valid @ModelAttribute Implant implant, BindingResult result){
ModelAndView mav=new ModelAndView();
mav.setViewName("../../admin/modifyImplant/"+id);
if (result.hasErrors()){
return mav;
}
implant.setId(id); //NOTICE WHAT I NEED TO DO HERE!
Implant oldImplant= impDAO.findById(id);
implant.setImplantinverters(oldImplant.getImplantinverters());
implant.setImplantpanels(oldImplant.getImplantpanels());
implant.setImplanttype(oldImplant.getImplanttype());
implant.setInverters(oldImplant.getInverters());
implant.setPvgis(oldImplant.getPvgis());
try{
impDAO.merge(implant); //here i call getSession().merge()
}catch(RuntimeException re){
return mav;
//TODO: errors
}
当我收到表单提交(这是更新)时,我遇到以下问题: 1.返回的植入物没有id(字段id = null) 2.相关实体也为空。
以下是植入实体
public class Implant implements java.io.Serializable {
// Fields
private Integer id;
private Pvgis pvgis;
private Gateway gateway;
private Implanttype implanttype;
@JsonIgnore //I NEED TO JSONIGNORE IT BECAUSE IT HAS A RECURSIVE CALL ON IMPLANT
private Users users;
@NotEmpty
private String nameimplant;
private String place;
private double latitude;
private double longitude;
private double expectedpower;
private double tolerance;
[...] and many other fields
和相关的implant.hbm.xml
<hibernate-mapping>
<class name="it.pstmarche.model.Implant" table="implant" schema="public">
<id name="id" type="integer">
<column name="id" />
<generator class="identity" />
</id>
<many-to-one name="pvgis" class="it.pstmarche.model.Pvgis" fetch="select">
<column name="idpvgis" />
</many-to-one>
<many-to-one name="gateway" class="it.pstmarche.model.Gateway" fetch="select">
<column name="idgateway" />
</many-to-one>
<many-to-one name="implanttype" class="it.pstmarche.model.Implanttype" fetch="select">
<column name="implanttype" />
</many-to-one>
<many-to-one name="users" class="it.pstmarche.model.Users" fetch="select" >
<column name="iduser" />
</many-to-one>
<property name="nameimplant" type="string">
<column name="nameimplant" not-null="true">
<comment>Name</comment>
</column>
我真的无法想象如何正确地进行更新,因为当我尝试从db(通过findById或直接查询)获取更新的实体时,我得到随机结果,有时我得到正确和更新的实体,有时我得到旧实体!!真是随意的。
我试过了: 1.删除没有结果的缓存(session.setCacheMode(CacheMode.IGNORE);) 2.添加getSession()。flush();的getSession()close()方法。在合并方法的最后,那:
public void merge(Implant currentImp){
//Session session = HibernateSessionFactory.getSessionFactory().openSession();
Transaction tx= getSession().beginTransaction();
if (currentImp.getId() != null) { // it is an update
getSession().merge(currentImp);
tx.commit();
//getSession().update(currentImp);
log.debug("MERGE");
getSession().flush();// THAT'S THE ADD
session.close(); //THIS IS ALSO
} else { // you are saving a new one
getSession().saveOrUpdate(currentImp);
tx.commit();
getSession().flush();
getSession().close();
log.debug("Save sou");
}
我真的无法确定使用Hibernate + Spring实现更新的正确方法是什么!任何帮助表示赞赏。感谢
编辑:也许我的问题不明确。目前的问题是,在我保存或合并一个实体后,随机地,当我搜索实体时(比如通过查询findById(int id)),我随机得到一个旧实体(我认为它仍然是在Hibernate会话中)。 覆盖此问题的唯一方法是清除会话(getSession()。clear()),但在此之后我显然会遇到懒惰异常 - 没有代理当我尝试获取我需要的实体的相关实体在清除的会话中!这是一个耻辱
2EDIT :谢谢Tim H.但是,我仍然面临与处理hibernate会话相关的问题。 前言:我使用每线程的hibernate会话,比如
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static Configuration configuration = new Configuration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
static {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateSessionFactory() {
}
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}
现在,假设我在Tomcat线程1 上从db加载实体x。实体值 100 。加载之后我无法关闭会话,因为它是懒惰的初始化(如果我关闭会话,我冒险以获得延迟初始化异常 - 无代理/会话)。< / p>
之后,我在线程2上更新实体x的值。值现在为50 。
最后,我加载回来的值,但tomcat让我进入线程1,其中实体仍然在线程的会话中,值仍然是100.我得到旧值而不是新值!! < / p>
所以,我不能关闭会话,直到我的jsp完成(我使用其上的惰性字段),我必须做这个反模式来关闭jsp结束时的会话:&lt;%HibernateSessionFactory.getSession ()。关(); %GT;那太可怕了!我将视图与模型结合在一起!有一种安全的模式吗?
答案 0 :(得分:1)
我或许可以解释你的一些问题。
如果请求参数与您实体的id属性(即隐藏的表单字段)匹配,则您的ID将仅绑定到您的实体。
对于其余的绑定,您可能希望使用所谓的“@ModelAttribute”技巧。基本上任何使用@ModelAttribute注释的方法都将在所有请求之前被调用,因此这个方法将返回一个实体,然后Spring将从表单中绑定您的支持对象,就像这样。
@ModelAttribute植入种植体 public Implant getBackingImplant(HttpServletRequest request) { if(request.getParameter(“id”)!= null return dao.getImplantByIdWithAllMyRelationshipsFilledIn(request.getParameter(“id”);
返回新的Implant(); }
所以现在spring会将你的表单绑定到getBackingImplant返回的实体。
至于你的保存没有工作,我真的不确定那个我不是一个休眠的家伙,但上面应该解决你的形式绑定困境。
答案 1 :(得分:0)
添加新答案,因为问题现在更加明确。记住merge返回它合并的实体,你丢弃了merge命令的结果,而是你应该将它返回给你的控制器。