Hibernate 在尝试使用合并方法更新对象时抛出 DataIntegrityViolationException

Posted

技术标签:

【中文标题】Hibernate 在尝试使用合并方法更新对象时抛出 DataIntegrityViolationException【英文标题】:Hibernate throws DataIntegrityViolationException when trying to update object using merge method 【发布时间】:2015-04-22 10:28:32 【问题描述】:

以前的update() 方法是抛出different object with the same identifier value was already associated with the session,所以我将dao 更改为merge。现在它给了org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

团队DAOImpl

public void updateTeam(Team team) 
        Team teamToUpdate = getTeam(team.getId());
        teamToUpdate.setName(team.getName());
        teamToUpdate.setRating(team.getRating());
        Set<TeamMember> teamMember = team.getTeamMembers();
        teamToUpdate.setTeamMembers(teamMember);
        getCurrentSession().merge(teamToUpdate);
    

团队实体

@Entity
@Table(name="teams")
public class Team 


    private Integer id;

    private String name;

    private Integer rating;

    private Set<TeamMember> teamMembers;

// ...
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "team_member", joinColumns =
    @JoinColumn(name = "FK_Team_id", referencedColumnName= "id"),
            inverseJoinColumns = @JoinColumn(name = "FK_Member_id", referencedColumnName = "id")
    )
    public Set<TeamMember> getTeamMembers() 
        return teamMembers;
    

    public void setTeamMembers(Set<TeamMember> teamMembers) 
        this.teamMembers = teamMembers;
    

Team 与团队成员建立多对多关系。在 SQL 级别上,它使用表完成:teamsmemberteam_member

违反了哪些约束?如何解决?

更新:

CREATE TABLE `member` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `teams` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  `rating` int(11) NOT NULL,
  `FK_Organization_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_Organization_id` (`FK_Organization_id`),
  CONSTRAINT `FK_Organization_id` FOREIGN KEY (`FK_Organization_id`) REFERENCES `organization` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `team_member` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `FK_Member_id` int(11) NOT NULL,
  `FK_Team_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `FK_Member_id` FOREIGN KEY (`id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_Team_id` FOREIGN KEY (`id`) REFERENCES `teams` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

错误 o.h.e.jdbc.spi.SqlExceptionHelper - 无法添加或更新子项 行:外键约束失败(db.team_member, 约束 FK_Member_id 外键 (id) 引用 member (id) 删除时没有操作更新没有操作)

数据:

UPDATE3

public Team getTeam(int id) 
        Team team = (Team) getCurrentSession().get(Team.class, id);
        return team;
    

更新4 P6Spy 帮助发现错误查询:

insert into team_member (FK_Team_id, FK_Member_id) values (2, 2);

返回:

[SQL] insert into team_member (FK_Team_id, FK_Member_id) values (2, 2);
[Err] 1452 - Cannot add or update a child row: a foreign key constraint fails (`db`.`team_member`, CONSTRAINT `FK_Member_id` FOREIGN KEY (`id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)

【问题讨论】:

这可能是您的级联问题。只是为了测试,尝试不设置团队成员并尝试设置另一个字段(不使用级联)以查看会发生什么。 如果没有在TeamDAOImpl 中设置teamMembers,它可以正常工作(更新除teamMembers 之外的所有成员) 您能否发布您在执行 update() 或合并时提供的示例值..? 所以你有Team teamToUpdate = getTeam(team.getId());,这基本上意味着teamteamToUpdate 指向同一个团队,对吗?如果是这样,请尝试将 Set&lt;TeamMember&gt; teamMember = team.getTeamMembers(); 更改为使用 teamToUpdate.getTeamMembers(); teamToUpdate 是另一个从传递的team 中选取更改的对象。建议更改后没有错误和更新发生 【参考方案1】:

问题出在team_member 表中的CONSTRAINT 定义中。而不是:

CONSTRAINT `FK_Member_id` FOREIGN KEY (`id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_Team_id` FOREIGN KEY (`id`) REFERENCES `teams` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION

必须是

CONSTRAINT `FK_Member_id` FOREIGN KEY (`FK_Member_id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_Team_id` FOREIGN KEY (`FK_Team_id`) REFERENCES `teams` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION

【讨论】:

以上是关于Hibernate 在尝试使用合并方法更新对象时抛出 DataIntegrityViolationException的主要内容,如果未能解决你的问题,请参考以下文章

hibernate:更新和合并方法之间的区别

Hibernate的merge()方法

Spring / Hibernate - 删除实体时抛出 StaleStateException

使用 POST 方法上传 JSON 对象时抛出错误请求异常

Mongoose 在使用 .save() 方法更新文档时抛出 E11000 重复键错误

使用jdbc更新数据后,hibernate 缓存对象不更新,与数据库不一致,同一个session中