我有一个 Keyword
和一个 KeywordType
作为实体。有很多类型很少的关键词。
当尝试保留类型的第二个关键字时,违反了唯一约束并且事务被回滚。
搜索SO我发现了几种可能性(其中一些来自不同的上下文,所以我不确定它们在这里的有效性) - 这篇文章和此处针对不同情况建议的锁定
按照此和这篇文章我想不会正常工作,因为我正在使用 Oracle 和不是 MySQL,并且希望将实现与 Hibernate 联系起来。
另一种解决方法是尝试首先在生成关键字的代码中检索类型,如果找到则将其设置在关键字上,如果没有则创建一个新类型。
那么,什么是最好的——最强大、最可移植(对于不同的数据库和持久性提供者)和最合理的方法呢?
谢谢。
涉及的实体:
public class Keyword {
@Id
@GeneratedValue
private long id;
@Column(name = "VALUE")
private String value;
@ManyToOne
@JoinColumn(name = "TYPE_ID")
private KeywordType type;
...
}
以及
@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = { "TYPE" }) })
public class KeywordType {
@Id
@GeneratedValue
private long id;
@Column(name = "TYPE")
private String type;
...
}
I have an Keyword
and a KeywordType
as entities. There are lots of keywords of few types.
When trying to persist the second keyword of a type, the unique constraint is violated and the transaction is rolled back.
Searching SO i found several possibilies (some of them from different contexts, so I'm not sure of their validity here) - this post and this post advise catching the Exception which would be of no use to me as I end up where I started and still need to somehow persist the keyword.
Same applies to locking proposed for a different situaltion here
Custom insert statements as proposed in this and this posts wouldn't work proper I guess, since I'm using Oracle and not MySQL and woulnd like to tie the implementation to Hibernate.
A different workaround would be trying to retrieve the type first in the code generating the keywords, and set it on the keyword if found or create a new one if not.
So, what would be the best - most robust, portable (for different databases and persistence providers) and sane approach here?
Thank you.
The involved entities:
public class Keyword {
@Id
@GeneratedValue
private long id;
@Column(name = "VALUE")
private String value;
@ManyToOne
@JoinColumn(name = "TYPE_ID")
private KeywordType type;
...
}
and
@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = { "TYPE" }) })
public class KeywordType {
@Id
@GeneratedValue
private long id;
@Column(name = "TYPE")
private String type;
...
}
发布评论
评论(3)
IMO,你的最后一个解决方案是正确的。搜索关键字类型,如果没有找到,则创建它。
捕获异常不是一个好的选择,因为
但请注意,使用此技术,您可能仍然有两个事务并行搜索相同类型,然后尝试并行插入它。其中一项事务会回滚,但频率会低得多。
Your last solution is the right one, IMO. Search for the keyword type, and if not found, create it.
Catching the exception is not a good option because
Note however that with this technique, you might still have two transactions searching for the same type in parallel, and then try to insert it in parallel. One of the transaction will rollback, but it will be much less frequent.
如果您使用 EJB 3.1 并且不介意序列化此操作,则使用容器管理并发的单例 bean 可以解决该问题。
If you're using EJB 3.1 and you don't mind serializing this operation, a singleton bean using container managed concurrency can solve the problem.
我会选择这个选项:
I would go for this option: