我正在尝试通过使用Spring和Hibernate的下表来实现双向多对多映射(question,tags,question_tag)
TABLE用户:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NOT NULL,
`password` varchar(255) DEFAULT NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
TABLE问题:
CREATE TABLE `question` (
`qid` int(11) NOT NULL AUTO_INCREMENT,
`questiontitle` varchar(255) DEFAULT NULL,
`questionbody` varchar(3000) DEFAULT NULL,
`uid` int(11) NOT NULL,
`votes` int(11) NOT NULL,
`created_on` DATETIME NOT NULL DEFAULT NOW(), -- or CURRENT_TIMESTAMP
PRIMARY KEY (`qid`),
CONSTRAINT `fk_user_id` FOREIGN KEY (`uid`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
TABLE标签:
CREATE TABLE `tags` (
`tagid` int(11) NOT NULL AUTO_INCREMENT,
`tag` varchar(255) DEFAULT NULL,
PRIMARY KEY (`tagid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表格问题标签:
CREATE TABLE `question_tag` (
`qid` int(11) NOT NULL,
`tagid` int(11) NOT NULL,
PRIMARY KEY (`qid`,`tagid`),
CONSTRAINT `fk_qt_qid` FOREIGN KEY (`qid`) REFERENCES `question` (`qid`),
CONSTRAINT `fk_tags_tagid` FOREIGN KEY (`tagid`) REFERENCES `tags` (`tagid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
使用的模型是
Question.Java
@Entity
@Table(name="question")
@NamedQuery(name="Question.findAll", query="SELECT q FROM Question q")
public class Question implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int qid;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="created_on")
private Date createdOn;
private String questionbody;
private String questiontitle;
private int uid;
private int votes;
//bi-directional many-to-one association to Answer
@OneToMany(mappedBy="question")
private Set<Answer> answers = new HashSet<>();
//bi-directional many-to-one association to QuestionComment
@OneToMany(mappedBy="question")
private Set<QuestionComment> questionComments = new HashSet<>();
//bi-directional many-to-many association to Tag
@ManyToMany(targetEntity = Tag.class,cascade = { CascadeType.ALL })
@JoinTable(name = "question_tag",
joinColumns = { @JoinColumn(name = "qid") },
inverseJoinColumns = { @JoinColumn(name = "tagid") })
private Set<Tag> tags;
//bi-directional many-to-one association to UserQuestionUpvote
@OneToMany(mappedBy="question")
private Set<UserQuestionUpvote> userQuestionUpvotes = new HashSet<>();
public Question() {
}
}
Tag.Java
@Entity
@Table(name="tags")
@NamedQuery(name="Tag.findAll", query="SELECT t FROM Tag t")
public class Tag implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private int tagid;
private String tag;
//bi-directional many-to-many association to Question
@ManyToMany(mappedBy = "tags")
private Set<Question> questions ;
public Tag() {
}
}
有一个questionServiceImpl类,它调用questionRepository.save方法。
@Service
public class QuestionServiceImpl implements QuestionService {
@Autowired
private QuestionRepository questionRepository;
@Override
public void save(Question question) {
// TODO Auto-generated method stub
questionRepository.save(question);
}
}
现在在控制器中,当对QuestionServiceImpl.save的调用被插入时,对表的问题进行了插入,对标签和question_tag进行了调用,但引发了无法添加或更新子行错误
Hibernate: insert into question (created_on, questionbody, questiontitle, uid, votes) values (?, ?, ?, ?, ?)
Hibernate: insert into tags (tag, tagid) values (?, ?)
Hibernate: insert into question_tag (qid, tagid) values (?, ?)
17:43:36.692 [http-bio-9191-exec-5] ERROR o.h.e.j.s.SqlExceptionHelper#129 Cannot add or update a child row: a foreign key constraint fails (`Forum`.`question_tag`, CONSTRAINT `fk_tags_tagid` FOREIGN KEY (`tagid`) REFERENCES `tags` (`tagid`))
Jul 10, 2018 5:43:36 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`Forum`.`question_tag`, CONSTRAINT `fk_tags_tagid` FOREIGN KEY (`tagid`) REFERENCES `tags` (`tagid`))
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:400)
at com.mysql.jdbc.Util.getInstance(Util.java:383)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:973)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3847)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3783)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2447)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2594)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1901)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2113)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2049)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2034)