私のプロジェクトには、User
、Role
、UserRole
、およびBloodGroup
エンティティがあります。まず、List<BloodGroup>
DBからUser
に設定します。それからUser
とRole
をUserRole
に誘います。その後、User
をDBに挿入し、UserRole
を挿入しようとしますが、エラーが発生します。 DBを見ると、BloodGroup
のIDがUser
テーブルに挿入されていません。
リストの最初のBloodGroup
を選択すると、エラーが発生します。他のオプションは正常です。
インターネットを見ると、cascade = CascadeType.ALL
が、これはBloodGroup
に同じデータを追加します。つまり、より多くのArh + BloodGroup
があります。
エンティティ:
@Entity
@Table(name="USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long userid;
@OneToMany(mappedBy="user")
private List<Userrole> userroles;
//bi-directional many-to-one association to Bloodgroup
@ManyToOne
@JoinColumn(name="BLOODGRUPID")
private Bloodgroup bloodgroup;
}
@Entity
public class Bloodgroup implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int bloodgroupid;
private String bloodgroupname;
@OneToMany(mappedBy="bloodgroup")
private List<User> users;
}
@Entity
public class Userrole implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long userroleid;
private Timestamp createddate;
private Timestamp deleteddate;
private String isactive;
//bi-directional many-to-one association to Role
@ManyToOne
@JoinColumn(name="ROLEID")
private Role role;
//bi-directional many-to-one association to User
@ManyToOne
@JoinColumn(name="USERID")
private User user;
}
コントローラ:
user.setBloodgroup(bloodGroupImpl.getBloodGroupById(bGroup));
user.setUserid(userImpl.insertUserProfile(user));
userRoleImpl.insertUserRole(user,role);
DAO:
public void insertUserRole(User user, Role role) {
Session session =getHibernateTemplate().getSessionFactory().getCurrentSession();
Userrole uRole = new Userrole();
uRole.setIsactive("1");
uRole.setRole(role);
uRole.setUser(user);
session.save(uRole);
session.flush();
}
public void insertUserProfile(User user) {
Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();
session.save(user);
}
ログ:
Hibernate:
insert
into
IU.Userrole
(userroleid, createddate, deleteddate, isactive, ROLEID, USERID)
values
(default, ?, ?, ?, ?, ?)
05.Şub.2012 19:23:29 com.Sun.faces.application.ActionListenerImpl processAction
SEVERE: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.iu.eblood.model.Bloodgroup
javax.faces.el.EvaluationException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.iu.eblood.model.Bloodgroup
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.Java:102)
at com.Sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.Java:102)
at javax.faces.component.UICommand.broadcast(UICommand.Java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.Java:775)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.Java:1267)
at com.Sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.Java:82)
at com.Sun.faces.lifecycle.Phase.doPhase(Phase.Java:103)
at com.Sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.Java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.Java:310)
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:305)
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.Java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:76)
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.Java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:76)
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:224)
at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:169)
at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:472)
at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:168)
at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:98)
at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:928)
at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:407)
at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:987)
at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:539)
at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:300)
at Java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.Java:886)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:908)
at Java.lang.Thread.run(Thread.Java:662)
カスケード依存関係を適切に定義するか、参照するエンティティを保存する前に参照するエンティティを保存することにより、問題が解決されます。カスケードの定義は、使用方法の微妙な違いがあるため、正しく行うのは本当に難しいです。
カスケードを定義する方法は次のとおりです。
@Entity
public class Userrole implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long userroleid;
private Timestamp createddate;
private Timestamp deleteddate;
private String isactive;
//bi-directional many-to-one association to Role
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="ROLEID")
private Role role;
//bi-directional many-to-one association to User
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="USERID")
private User user;
}
このシナリオでは、ユーザーロールを保存、更新、削除などするたびに、関連付けられたロールとユーザーも保存、更新されます...
繰り返しますが、ユーザーロールを更新するときにユーザーまたはロールを変更しないようにユースケースが要求する場合は、ユーザーロールを変更する前にユーザーまたはロールを保存するだけです
さらに、双方向の関係には一方向の所有権があります。この場合、ユーザーはBloodgroupを所有しています。したがって、カスケードはユーザー->血液型からのみ続行します。繰り返しますが、ユーザーをBloodgroupに関連付けるには、ユーザーをデータベースに保存する(アタッチするか、非一時的にする)必要があります。
同様の問題があり、参照されたエンティティが最初に保存されていることを確認しましたが、同じ例外で失敗し続けます。数時間の調査の後、参照されたエンティティの「バージョン」列がNULLであったことが問題であることが判明しました。私の特定のセットアップでは、最初にHSQLDB(ユニットテスト)に次のような行を挿入しました。
INSERT INTO project VALUES (1,1,'2013-08-28 13:05:38','2013-08-28 13:05:38','aProject','aa',NULL,'bb','dd','ee','ff','gg','ii',NULL,'LEGACY','0','CREATED',NULL,NULL,1,'0',NULL,NULL,NULL,NULL,'0','0', NULL);
上記の問題は、hibernateによって使用されるバージョン列がnullに設定されているため、オブジェクトが正しく保存された場合でも、Hibernateはそれを未保存と見なしたことです。バージョンにNON-NULL(この場合は1)値が含まれていることを確認すると、例外が消え、すべてが正常に機能しました。
他の誰かが同じ問題を抱えている場合に備えて、ここに置いています。これを理解するのに長い時間がかかり、解決策は上記とは完全に異なっているからです。
@Cascadeを@ManyToOne属性に追加してこの問題を解決しました。
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@ManyToOne
@JoinColumn(name="BLOODGRUPID")
@Cascade({CascadeType.MERGE, CascadeType.SAVE_UPDATE})
private Bloodgroup bloodgroup;
私の場合、マージo saveメソッドの前にオブジェクトの参照オブジェクトをNULLに設定すると、問題が解決します。私の場合、参照オブジェクトはカタログでしたが、保存する必要はありません。でも。
fisEntryEB.setCatStatesEB(null);
(fisEntryEB) getSession().merge(fisEntryEB);
参照オブジェクトを渡すのではなく、保存したオブジェクトを渡すのではなく、以下が私の問題を解決する説明です。
//wrong
entityManager.persist(role);
user.setRole(role);
entityManager.persist(user)
//right
Role savedEntity= entityManager.persist(role);
user.setRole(savedEntity);
entityManager.persist(user)