传递性持久性& “分离的实体继续坚持”

时间:2013-06-26 17:45:14

标签: spring hibernate jpa-2.0 nhibernate-mapping

我想(希望)我正在做所有正确的事情。谷歌搜索了很多,找不到什么是错的。

Profile可以有多个Appointment个。 每个Appointment都有Department

  • 部门被加载并存储在一组中,当然是分离的。
  • 约会已创建,并从上述集合中获得部门。
  • 约会已添加到个人资料中。
  • 配置文件是持久的。
  • 为部门
  • 抛出传递给persist的分离实体

资料:

@Entity
@Table(name = "PROFILE")
public class Profile {
/**
 * 
 */
private Set<Appointment> appointments = new HashSet<Appointment>();

/**
 * @return the appointments
 */

@OneToMany(mappedBy = "profile", cascade = { CascadeType.PERSIST,
        CascadeType.MERGE })
public Set<Appointment> getAppointments() {
    return appointments;
}

/**
 * @param appointments
 *            the appointments to set
 */
public void setAppointments(Set<Appointment> appointments) {
    this.appointments = appointments;
}

/**
 * 
 * @param apt
 */
public void addAppointment(Appointment apt) {
    apt.setProfile(this);
    appointments.add(apt);
}
}

预约:

@Entity
@Table(name = "APPOINTMENT")
public class Appointment {
/**
 * 
 */
private Department department;
private Profile profile;


/**
 * @return the department
 */
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY)
@JoinColumn(name = "DEPARTMENT_ID")
@Index(name = "IDX_APPOINTMENT_DEPARTMENT")
@ForeignKey(name = "FK_APPOINTMENT_DEPARTMENT")
public Department getDepartment() {
    return department;
}

/**
 * @param department
 *            the department to set
 */
public void setDepartment(Department department) {
    this.department = department;
}

/**
 * @return the profile
 */
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY)
@JoinColumn(name = "PROFILE_ID")
@Index(name = "IDX_APPOINTMENT_PROFILE")
@ForeignKey(name = "FK_APPOINTMENT_PROFILE")
public Profile getProfile() {
    return profile;
}

/**
 * @param profile
 *            the profile to set
 */
public void setProfile(Profile profile) {
    this.profile = profile;
}
}

系:

@Entity
@Table(name = "DEPARTMENT")
public class Department {
/**
 *
 */
private Set<Appointment> appointments = new HashSet<Appointment>();
private Set<Department> children = new HashSet<Department>();
private Department parent;


/**
 * @return the appointments
 */
@OneToMany(mappedBy = "department")
public Set<Appointment> getAppointments() {
    return appointments;
}

/**
 * @param appointments
 *            the appointments to set
 */
public void setAppointments(Set<Appointment> appointments) {
    this.appointments = appointments;
}

/**
 * @return the children
 */
@OneToMany(mappedBy = "parent", cascade = { CascadeType.PERSIST,
        CascadeType.MERGE })
public Set<Department> getChildren() {
    return children;
}

/**
 * @param children
 *            the children to set
 */
public void setChildren(Set<Department> children) {
    this.children = children;
}

/**
 * @return the parent
 */
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENTDEPARTMENT_ID")
@Index(name = "IDX_DEPARTMENT_CHILDREN")
@ForeignKey(name = "FK_DEPARTMENT_CHILDREN")
public Department getParent() {
    return parent;
}

/**
 * @param parent
 *            the parent to set
 */
public void setParent(Department parent) {
    this.parent = parent;
}
}

错误的@Service代码:

@Transactional(propagation = Propagation.REQUIRED)
private Profile addNewProfile(ProfileJxb profileJxb) {
    logger.entry();

    Profile profile = new Profile(profileJxb);
    for (AppointmentJxb aptJxb : profileJxb.getAppointments()
            .getAppointmentJxb()) {
        Appointment apt = new Appointment(aptJxb);
        Department d = getDepartmentByName(aptJxb.getDepartment()); // previously fetched
        apt.setDepartment(d);
        // d.getAppointments().add(apt); // another failed attempt, this results in LazyInitException

        profile.addAppointment(apt);
    }

    profile = profileDao.makePersistent(profile); // Exception thrown here!

    logger.exit();
    return profile;
}

我希望我遗漏了一些东西,因为我正在获取并将Department设置为持久状态以避免此异常。

谢谢。

1 个答案:

答案 0 :(得分:2)

当您需要保存通过级联关系引用分离实体的新实体时,您必须使用merge()而不是persist(),但这不是解决此问题的最佳方法

真正的问题是department关系已经层叠。当引用所讨论的实体逻辑上拥有的实体时,级联是有意义的。但在您的情况下,您有一组预定义的Department s,它们是单独管理的。因此,您永远不需要将任何操作从Appointment级联到Department

因此,最佳解决方案是从department关系中删除级联。