在@ManyToMany关系中更新后,Hibernate不需要/意​​外删除语句

时间:2018-01-06 22:44:57

标签: java spring hibernate many-to-many cascade

我将提供一些关于我的webapp的一般信息(我现在只提到有问题的表)。所以,我有3个桌子Trainer,Event和Event-Trainer。

CREATE TABLE `Event` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Title` varchar(1000) DEFAULT NULL,
  `Date` varchar(45) DEFAULT NULL,
  `Time` varchar(45) DEFAULT NULL,
  `Duration` varchar(20) DEFAULT NULL,
  `Location` varchar(45) DEFAULT NULL,
  `Days` int(11) DEFAULT '1',
  `Price` double DEFAULT NULL,
  `PlaceLimit` int(11) DEFAULT NULL,
  `CategoryID` int(11) DEFAULT NULL,
  `Notes` varchar(1000) DEFAULT '(No notes)',
  PRIMARY KEY (`ID`),
  KEY `CategoryID_idx` (`CategoryID`),
  CONSTRAINT `CategoryID` FOREIGN KEY (`CategoryID`) REFERENCES `Category` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
)

CREATE TABLE `Trainer` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `FirstName` varchar(45) DEFAULT NULL,
  `LastName` varchar(45) DEFAULT NULL,
  `Email` varchar(45) DEFAULT NULL,
  `Phone` varchar(45) DEFAULT NULL,
  `City` varchar(45) DEFAULT NULL,
  `Picture` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) 
CREATE TABLE `Event-Trainer` (
  `EventID` int(11) NOT NULL,
  `TrainerID` int(11) NOT NULL,
  PRIMARY KEY (`EventID`,`TrainerID`),
  KEY `FK_TrainerID` (`TrainerID`),
  CONSTRAINT `FK_EventID_2` FOREIGN KEY (`EventID`) REFERENCES `Event` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_TrainerID_2` FOREIGN KEY (`TrainerID`) REFERENCES `Trainer` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
)

这些是实体类

//Event.java
@Entity
@Table(name = "Event", schema = "business-club")
public class Event {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private int id;

    ...    

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "CategoryID")
    private Category category;



    @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}
            , fetch = FetchType.EAGER)
    @JoinTable(
            name = "`Event-Trainer`",
            joinColumns = @JoinColumn(name = "EventID"),
            inverseJoinColumns = @JoinColumn(name = "TrainerID")
    )
    private List<Trainer> trainers;
...
}

//Trainer.java
    @Entity
@Table(name = "Trainer", uniqueConstraints = {@UniqueConstraint(columnNames = {"FirstName","LastName","Email"})})
public class Trainer {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Column(name="ID")
    private int id;

    ...

    @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinTable(
            name="`Event-Trainer`",
            joinColumns = @JoinColumn(name = "TrainerID"),
            inverseJoinColumns = @JoinColumn (name="EventID")
    )
    private List<Event> events;

现在让我们解决这个问题,我遇到了一个奇怪的Hibernate行为,在我更新了一个Trainer后,它“意外”删除了事件培训师表中与该培训师相关的记录,这里是我更新后的hibernate日志培训师

Hibernate: update Trainer set City=?, Email=?, FirstName=?, LastName=?, Phone=?, Picture=?  where ID=?
Hibernate: delete from `Event-Trainer` where TrainerID=?

我尝试更改两个实体中的级联类型并且它不起作用,我将获取类型更改为LAZY并且我在更新时遇到了异常(如果有人向我解释这一点,我会非常感激,尽管我不这样做认为这是一个大问题,至少现在是这样)

如果需要,我会发布更多信息

3 个答案:

答案 0 :(得分:0)

我认为桌面'Event-Trainer'上的CascadeType.DETACH导致了这个问题。 您是否能够在“培训师”表中看到更新的值?

答案 1 :(得分:0)

多对多关系的映射不正确。您应该使用@ManyToMany中的mappedBy属性创建一个主服务器和另一个服务器。

答案 2 :(得分:0)

感谢Mohamed Gara,这是解决我问题的方法 我改变了

//Trainer Entity
    @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinTable(
            name="`Event-Trainer`",
            joinColumns = @JoinColumn(name = "TrainerID"),
            inverseJoinColumns = @JoinColumn (name="EventID")
    )
    private List<Event> events;

@ManyToMany(mappedBy = "trainers",fetch = FetchType.EAGER)
private List<Event> events;

//Event Entity
    @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}
            , fetch = FetchType.EAGER)
    @JoinTable(
            name = "`Event-Trainer`",
            joinColumns = @JoinColumn(name = "EventID"),
            inverseJoinColumns = @JoinColumn(name = "TrainerID")
    )
    private List<Trainer> trainers;

@ManyToMany(fetch = FetchType.EAGER)
private List<Trainer> trainers;

我还必须将我的表Event-Trainer的名称更改为Event_Trainer,并将主键的名称从EventID,TrainerID更改为events_ID,trainers_ID。 (我在抛出一些例外后这样做了)

编辑1

删除分配给事件的培训师时出现异常,因此我将两个外键的ON DELETE和ON UPDATE从NO ACTION更改为CASCADE,并在两个实体的@ManyToMany注释中指定了级联类型

@ManyToMany( ... cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})