我正在尝试使用带有注释的 Hibernate3 对单向 OneToMany 关系进行建模。场景是一个用户有很多文章,一篇文章有很多用户。在工作流程中,用户可以阅读其中一篇文章,在这种情况下,我想将其移动到“已读”文章的持久列表中。就 Java 模型而言,这就是一对多关系发生的地方。用户拥有属于该个人用户的“已读”文章列表。
问题是表可以有很多用户和很多文章,所以主键应该是 user_id 和 article_id 的组合。但是,在我当前的设置中,article_id 被设置为主键。这造成了一个错误,我可以在第一次准备好时将“已读”文章插入表中,但一旦第二个用户尝试阅读该文章,它就会引发重复键异常。
这是我的Java设置:
@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
@JoinTable(name = "educational_article_read", joinColumns = {
@JoinColumn(name = "user_id")}, inverseJoinColumns = {
@JoinColumn(name = "article_id")})
@Cascade({CascadeType.ALL})
private List<EducationalArticleModel> articles_read = new ArrayList<EducationalArticleModel>();
这是生成的表模式:
mysql> describe educational_article_read;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| user_id | int(11) | NO | MUL | NULL | |
| article_id | int(11) | NO | PRI | NULL | |
+------------+---------+------+-----+---------+-------+
2 rows in set (0.05 sec)
错误堆栈跟踪:
org.springframework.dao.DataIntegrityViolationException: Duplicate entry '55' for key 'article_id'; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Duplicate entry '55' for key 'article_id'
at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:138)
at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:594)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:476)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:387)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.bosch.dao.UserDAO$$EnhancerByCGLIB$$f17df281.update(<generated>)