Spring Data / Hibernate-传播生成的密钥

时间:2018-08-19 01:46:13

标签: java spring hibernate

通常,我可以通过Google的方式摆脱在这里提出问题(谢谢社区),但我在这里有些困惑。此问题与调用JpaRepository.save()

时将生成的密钥传播到连接的对象有关。

我们有这样定义的实体:

父对象

@Entity
@Table(name = "appointment")
public class Appointment implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "APPT_ID", columnDefinition = "integer")
    private Long apptId;

    ...

    @OneToMany(targetEntity = ApptReminder.class, mappedBy = "appointment", cascade = {
            CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.EAGER)
    @NotFound(action = NotFoundAction.IGNORE)
    private List<ApptReminder> apptReminders = new ArrayList<>();
}

子对象:

@Entity
@Table(name = "appt_reminder")
public class ApptReminder implements Serializable {
    @EmbeddedId
    private ReminderKey reminderKey = new ReminderKey();

    ...

    @ManyToOne
    @NotFound(action = NotFoundAction.IGNORE)
    private Appointment appointment;
}

嵌入式ID类

@Embeddable
public class ReminderKey implements Serializable {

    @Column(name = "APPT_ID", columnDefinition = "integer")
    private Long apptId;

    @Column(name = "CALL_NUM", columnDefinition = "integer")
    private Short callNum;

    ....
}

存储库:

public interface AppointmentRepository extends JpaRepository<Appointment, Long> {
}

我们有一堆悬挂在子对象上的对象,它们共享嵌入式键属性。当我们在父对象appointmentRepository.save(appointment)上调用save时,将保存子对象,但是插入的第一个约会的appt_id会自动生成一个键1,而第一个apptReminder记录的appt_id会为0。

这会影响所有共享ReminderKey的嵌入式ID并具有相似且可预测效果的对象。

当我们在顶级实体上调用appoitnmentRepository.save(appointment)时,如何获得自动生成的密钥以传播到子实体?我觉得这应该很容易。可能是因为我布局映射的方式或使用嵌入ID的某种方式阻止了此工作。

最后要注意的一点是,它在开发中针对H2数据库运行,但随后将针对MySQL使用。这可能归因于H2的MySQL兼容性

2 个答案:

答案 0 :(得分:0)

我认为您需要使用JoinColumns注释将Appointment apptId嫁接到ReminderKey apptId

答案 1 :(得分:0)

已解决:

在持续操作上从apptReminder分离约会:

public class Appointment implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "APPT_ID", columnDefinition = "integer")
    private Long apptId;

    ...

    @OneToMany(targetEntity = ApptReminder.class, mappedBy = "appointment", cascade = CascadeType.DETACH, fetch = FetchType.EAGER)
    @NotFound(action = NotFoundAction.IGNORE)
    private List<ApptReminder> apptReminders = new ArrayList<>();
}

创建一个DAO来处理持久性操作:

@Repository
public class AppointmentDAO {

    @Autowired
    private AppointmentRepository appointmentRepository;

    @Autowired
    private ApptReminderRepository apptReminderRepository;

    public List<Appointment> save(List<Appointment> appointments) {
        appointments.forEach(a -> this.save(a));
        return appointments;
    }

    public Appointment save(Appointment appointment) {
        final Appointment appt = appointmentRepository.save(appointment);
        List<ApptReminder> apptReminders = appointment.getApptReminders();
        apptReminders.forEach(a -> {
            a.getReminderKey().setApptId(appt.getApptId());
            a.getReminderTags().forEach(t -> t.setApptId(appt.getApptId()));
            a.getReminderMessages()
                    .forEach(m -> m.getReminderMessageKey().setApptId(appt.getApptId()));
            a.getMsgQueueReminder().setApptId(appt.getApptId());
        });
        apptReminderRepository.saveAll(apptReminders);
        return appointment;
    }
}