2012-02-05 36 views
19

Trong dự án của tôi, tôi có các đối tượng User, Role, UserRoleBloodGroup. Trước tiên, tôi lấy List<BloodGroup> từ DB và đặt thành User. Sau đó, tôi cung cấp cho UserRole entites đến UserRole. Sau đó tôi chèn User vào DB, sau đó tôi cố gắng để chèn UserRole, nhưng tôi nhận được một lỗi. Khi tôi tìm đến DB, ID của BloodGroup không được đưa vào bảng User.org.hibernate.TransientObjectException: tham chiếu đối tượng một cá thể tạm thời chưa lưu - lưu phiên bản tạm thời trước khi xóa

Nếu tôi chọn BloodGroup đầu tiên trong danh sách, tôi gặp lỗi. Các tùy chọn khác là bình thường.

Tôi xem Internet, tôi tìm thấy cascade = CascadeType.ALL, nhưng điều này thêm cùng một dữ liệu vào BloodGroup, có nghĩa là tôi có nhiều Arh + BloodGroup.

Đối tượng:

@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; 

} 

Bộ điều khiển:

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); 
} 

Log:

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) 
+0

Ông có thể cung cấp mã mà ném lỗi? chỉ để xem cách bạn đang lưu các phiên bản. – ivowiblo

+2

Thay vì thử những thứ ngẫu nhiên tìm thấy trên internet, bạn nên cố gắng hiểu ý nghĩa của lỗi, phát hiện vị trí ngoại lệ được ném và sửa lỗi. Hiển thị cho chúng tôi dấu vết ngăn xếp đầy đủ và mã gây ra ngoại lệ này để được ném. –

Trả lời

39

vấn đề của bạn sẽ được giải quyết bằng cách định nghĩa đúng depedencies tầng hoặc bằng cách tiết kiệm các đối tượng tham chiếu trước khi lưu đơn vị mà tài liệu tham khảo. Xác định xếp tầng thực sự phức tạp để có được quyền vì tất cả các biến thể tinh tế trong cách chúng được sử dụng.

Đây là cách bạn có thể định nghĩa thác:

@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; 

} 

Trong kịch bản này, mỗi khi bạn lưu, cập nhật, xóa, vv Userrole, Vai trò assocaited và người dùng cũng sẽ được lưu lại, cập nhật ...

lần nữa, nếu trường hợp sử dụng của bạn đòi hỏi bạn không sửa đổi tài khoản hoặc Role khi cập nhật Userrole, sau đó chỉ cần lưu tài khoản hoặc Vai trò trước khi sửa đổi Userrole

Bên cạnh đó, mối quan hệ hai chiều có quyền sở hữu một chiều. Trong trường hợp này, người dùng sở hữu nhóm máu. Vì vậy, thác sẽ chỉ tiến hành từ User -> Bloodgroup. Một lần nữa, bạn cần phải lưu người dùng vào cơ sở dữ liệu (đính kèm nó hoặc làm cho nó không thoáng qua) để kết hợp nó với nhóm máu.

10

Tôi đã gặp sự cố tương tự và mặc dù tôi đã đảm bảo rằng các thực thể được tham chiếu đã được lưu trước tiên nhưng vẫn không thành công với cùng một ngoại lệ. Sau nhiều giờ điều tra, hóa ra là do cột "phiên bản" của thực thể được tham chiếu là NULL. Trong thiết lập riêng của tôi, tôi đã được chèn nó lần đầu tiên trong một HSQLDB (đó là một thử nghiệm đơn vị) liên tiếp như thế:

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); 

Vấn đề ở trên là cột phiên bản được sử dụng bởi Hibernate đã được thiết lập để null, vì vậy ngay cả khi đối tượng được lưu chính xác, Hibernate coi nó là chưa được lưu. Khi đảm bảo phiên bản có giá trị NON-NULL (1 trong trường hợp này), ngoại lệ biến mất và mọi thứ hoạt động tốt.

Tôi đặt nó ở đây trong trường hợp người khác có cùng một vấn đề, vì điều này đã cho tôi một thời gian dài để tìm ra điều này và giải pháp hoàn toàn khác so với ở trên.

+2

Hibernate luôn mang đến những thông báo lỗi tồi tệ nhất ... cuộc sống làm việc của tôi ... – Serge

+1

Cảm ơn câu trả lời này .... cùng một vấn đề đã khiến tôi xé tóc ra ... Tôi đã thử tất cả các loại giao dịch và các tùy chọn thác chỉ để thấy rằng vấn đề là một trường phiên bản NULL ... không thể tìm thấy bất cứ nơi nào khác mà tài liệu vấn đề này. –

+1

Cảm ơn bạn cho câu trả lời này - đây là trường hợp với tôi, khi tạo người dùng với CommandLineRunner trong khởi động mùa xuân (cũng có một số giá trị với NULL, không bao giờ có thể đoán được đối tượng được coi là chưa được lưu trong trường hợp này) – lenach87

1

Tôi giải quyết vấn đề này thêm @Cascade vào thuộc tính @ManyToOne.

import org.hibernate.annotations.Cascade; 
import org.hibernate.annotations.CascadeType; 

@ManyToOne 
@JoinColumn(name="BLOODGRUPID") 
@Cascade({CascadeType.MERGE, CascadeType.SAVE_UPDATE}) 
private Bloodgroup bloodgroup; 
0

Thay vì đối tượng tham khảo qua thông qua lưu đối tượng, dưới đây là lời giải thích mà giải quyết vấn đề của tôi:

//wrong 
entityManager.persist(role); 
user.setRole(role); 
entityManager.persist(user) 

//right 
Role savedEntity= entityManager.persist(role); 
user.setRole(savedEntity); 
entityManager.persist(user) 
Các vấn đề liên quan