私はこの問題を抱えています:
エンティティでビューを準備します
@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>
エンティティのフィールドについても同様です。エンティティには、外部キーで接続されたいくつかのエンティティが関連付けられています (implanttype、implantinverter、implantpanels など)。
提出物はこのコントローラーに行きます:
@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
}
フォームの送信を取得すると (これは更新です)、次の問題があります。
以下はインプラントエンティティです
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>
データベースから更新されたエンティティを取得しようとすると(findByIdまたは直接クエリを介して)ランダムな結果が得られるため、更新を正しく行う方法が本当にわかりません。正しい更新されたエンティティを取得することもあれば、古いものを取得することもあります実在物!!本当にランダム。
私が試した: 1. キャッシュを削除する ( session.setCacheMode(CacheMode.IGNORE); ) 結果はありません 2. getSession().flush(); を追加します。getSession().close(); merge メソッドの最後で、次のことを行います。
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()) ですが、この後明らかに Lazy 例外が発生します -必要なエンティティの関連エンティティを取得しようとすると、プロキシはありません。セッション!残念です
2EDIT:Tim Hに感謝します。ただし、休止状態セッションの処理に関連する問題にまだ直面しています。序文:私はスレッドごとに休止状態のセッションを使用します
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 でデータベースからエンティティ x をロードするとします。エンティティ値は100です。セッションは遅延初期化されているため、ロード後にセッションを閉じることができません(また、セッションを閉じると、遅延初期化例外 (プロキシ/セッションなし) が発生するリスクがあります)。
その後、スレッド 2 でエンティティ x の値を更新します。現在の値は 50です。
最後に、値をロードし直しましたが、Tomcat はエンティティがまだスレッドのセッションにあり、値がまだ 100 であるスレッド 1 に移動しました。新しい値ではなく古い値を取得します!!
したがって、jsp が終了するまでセッションを閉じることはできません (その上で遅延フィールドを使用します)。次の方法で jsp の最後にセッションを閉じるには、このアンチパターンを実行する必要があります: <% HibernateSessionFactory.getSession().close (); %> そしてそれは恐ろしいことです! ビューとモデルを結合します! これを安全に行うためのパターンはありますか??