Подтвердить что ты не робот

Org.hibernate.TransientObjectException: объект ссылается на несохраненный экземпляр переходного процесса - сохраняет временный экземпляр перед промывкой

В моем проекте у меня есть объекты User, Role, UserRole и BloodGroup. Сначала я беру List<BloodGroup> из БД и устанавливаю значение User. Затем я даю User, а Role - UserRole. После этого я вставляю User в DB, ​​затем пытаюсь вставить UserRole, но получаю сообщение об ошибке. Когда я смотрю на БД, идентификатор BloodGroup не вставлен в таблицу 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);
}

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)
4b9b3361

Ответ 1

ваша проблема будет решена путем правильного определения каскадных зависимостей или сохранения привязанных объектов перед сохранением ссылки на объект. Определение каскадирования действительно сложно, потому что все тонкие вариации в том, как они используются.

Вот как вы можете определить каскады:

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

}

В этом случае каждый раз, когда вы сохраняете, обновляете, удаляете и т.д. Userrole, ассоциированная роль и пользователь также будут сохранены, обновлены...

Опять же, если ваш вариант использования требует, чтобы вы не изменяли пользователя или роль при обновлении Userrole, просто сохраните пользователя или роль перед изменением Userrole

Кроме того, двунаправленные отношения имеют одностороннее право собственности. В этом случае пользователь владеет Bloodgroup. Поэтому каскады будут поступать только из User → Bloodgroup. Опять же, вам нужно сохранить пользователя в базе данных (присоединить его или сделать его непрерывным), чтобы связать его с Bloodgroup.

Ответ 2

У меня была аналогичная проблема, и хотя я убедился, что объекты, на которые ссылаются, были сохранены сперва, он продолжает терпеть неудачу с тем же исключением. После нескольких часов исследования выясняется, что проблема заключалась в том, что столбец "версия" ссылочного объекта был NULL. В моей конкретной установке я сначала вставлял ее в HSQLDB (это была unit test) такая строка:

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 в этом случае), исключение исчезло, и все работало нормально.

Я помещаю его здесь, если у кого-то была такая же проблема, так как это заняло у меня много времени, чтобы понять это, и решение полностью отличается от вышеупомянутого.

Ответ 3

Я решил эту проблему, добавив @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;

Ответ 4

Вместо передачи объекта ссылки передан сохраненный объект, ниже приведено объяснение, которое решает мою проблему:

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

//right
Role savedEntity= entityManager.persist(role);
user.setRole(savedEntity);
entityManager.persist(user)