我有一个实体,其中有一个非ID字段必须从序列中设置。 目前,我会获取序列的第一个值,并将其存储在客户端端,然后从该值进行计算。
但是,我正在寻找一种更好的方法来做到这一点。我已经实现了一种获取下一个序列值的方式:
public Long getNextKey()
{
Query query = session.createSQLQuery( "select nextval('mySequence')" );
Long key = ((BigInteger) query.uniqueResult()).longValue();
return key;
}
然而,这种方式会显著降低性能(创建约5000个对象的速度减缓了3倍,从5740毫秒变为13648毫秒)。
我曾试图添加一个“假”的实体:
@Entity
@SequenceGenerator(name = "sequence", sequenceName = "mySequence")
public class SequenceFetcher
{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
private long id;
public long getId() {
return id;
}
}
然而,这种方法也行不通(返回的所有 Id 都为 0)。
有没有人能够指导我如何高效地使用 Hibernate 获取下一个序列值?
编辑:经过调查,我发现调用 Query query = session.createSQLQuery("select nextval('mySequence')");
的效率远不及使用 @GeneratedValue
- 这是因为 Hibernate 在访问由 @GeneratedValue
描述的序列时,某种方式成功地减少了获取次数。
例如,当我创建 70,000 个实体时(因此从同一序列获取 70,000 个主键),我得到了我需要的一切。
然而,Hibernate 只发出了 1404 条 select nextval ('local_key_sequence')
命令。注意:在数据库端,缓存设置为 1。
如果我尝试手动获取所有数据,那么将需要 70,000 次查询,因此性能存在很大差异。有没有人知道 Hibernate 的内部功能,以及如何手动复制它?
resolveDialect()
之前,我必须使用DatabaseMetaDataDialectResolutionInfoAdapter
来包装connection.getMetaData()
的结果。感谢@punitpatel! - Ricardo van den Broekdialect.getSequenceNextValString()
,对于不支持序列的数据库将无法正常工作... - Ricardo van den BroekdoReturningWork
(可能比3更新)。此外,getSequenceNextValString(...)
不会引用或验证序列名称,并且在本评论发布时存在注入漏洞。因此,不要从用户输入中获取序列名称,尽管这种情况相当不太可能发生。 - xenoterracide