【问题标题】:Referential integrity constraint violation - failing when add more then 2 records违反参照完整性约束 - 添加超过 2 条记录时失败
【发布时间】:2018-05-16 07:17:03
【问题描述】:

当我加载我的初始测试数据时,我检索到完整性约束违规异常。只有当我使用 addShift 方法添加超过 2 条记录时才会发生这种情况。我在内存数据库中使用 h2。

加载中:

public void load() {
    shiftService.addShift(1, LocalDate.now(), ShiftType.DAY, 1);
    shiftService.addShift(2, LocalDate.now().plusDays(1), ShiftType.NIGHT, 1);
    shiftService.addShift(2, LocalDate.now().plusDays(5), ShiftType.NIGHT, 2);
}

轮班服务:

@Transactional
public void addShift(long userId, LocalDate shiftDate, ShiftType shiftType, long groupId) {
    Optional<User> user = userService.findOne(userId);
    if (user.isPresent()) {
        Optional<Group> group = groupService.getOne(groupId);
        if (group.isPresent()) {
            Shift shift = new Shift(shiftDate, shiftType, group.get());
            user.get().addShift(shift);
        }
    }
}

原因:

org.h2.jdbc.JdbcSQLException: Referential integrity constraint 
violation: "FKG5R8KJRL3GG3EKESMHT77GO7L: PUBLIC.SHIFT FOREIGN KEY(ID) 
REFERENCES PUBLIC.GROUPS(ID) (3)"; SQL statement:
insert into shift (id, group_id, shift_date, shift_type) values (null, ?, ?, 
?) [23506-196]

型号:

换档:

@Entity
public class Shift {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private LocalDate shiftDate;
    private ShiftType shiftType;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "user_shifts", joinColumns = @JoinColumn(name = "shift_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"))
    private Set<User> users = new HashSet<>();

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "group_id")
    private Group group;

组:

@Entity
@Table(name = "groups") // Group is reserved name in SQL
public class Group {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "user_group", joinColumns = @JoinColumn(name = "group_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"))
    private Set<User> users = new HashSet<>();

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "moderator_group", joinColumns = @JoinColumn(name = "group_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"))
    private Set<User> moderators = new HashSet<>();

    @OneToMany(mappedBy = "id", cascade = CascadeType.ALL)
    private Set<Shift> shifts;

用户:

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String email;
    private String password;
    private String firstName;
    private String lastName;
    private String phone;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(
            name = "user_authority",
            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "name")}
    )
    private Set<Authority> authorities = new HashSet<>();

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
            name = "user_group",
            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "group_id", referencedColumnName = "id")}
    )
    private Set<Group> usingGroups = new HashSet<>();

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
            name = "moderator_group",
            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "group_id", referencedColumnName = "id")}
    )
    private Set<Group> moderatingGroups = new HashSet<>();

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(
            name = "user_shifts",
            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "shift_id", referencedColumnName = "id")}
    )
    private Set<Shift> shifts = new HashSet<>();

你知道为什么我会得到这个异常吗?

【问题讨论】:

  • 数据库中存在id=2的组?
  • 是的,它存在,否则它不会被保存(可选检查是否)。我也通过仅向第 1 组添加班次来测试它。结果是一样的。
  • @DawidKunert 我可能是错的,但我认为你不需要来自关系双方的@JoinTable/@JoinTable。
  • @varren 据我所知,这是推荐的解决方案,但我认为这与那里无关,因为例外是说问题在于 Shift 和 Group 之间的 ManyToOne 关系
  • @DawidKunert 是的,但我仍然会检查它,有类似的问题,双面连接和 btw stackoverflow.com/questions/7869450/… 完全不相关的异常也看看docs.oracle.com/javaee/7/api/javax/persistence/JoinTable.html It is applied to the owning side of an association.

标签: java spring jdbc spring-data-jpa h2


【解决方案1】:

您在Group 中的映射是错误的。

@OneToMany(mappedBy = "id", cascade = CascadeType.ALL)
private Set<Shift> shifts;

应该是这样的:

@OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
private Set<Shift> shifts;

说明:

Hibernate 在shift 中的id 和group 中的id 之间添加外键约束。您可能正在添加 2 个组,并且在您尝试添加超过 2 个班次后,约束不满足,因为不存在 id 为 3 的组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 2017-12-25
    相关资源
    最近更新 更多