我将提供一些关于我的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并且我在更新时遇到了异常(如果有人向我解释这一点,我会非常感激,尽管我不这样做认为这是一个大问题,至少现在是这样)
如果需要,我会发布更多信息
答案 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})