场景:使用默认的 Postgres 序列生成器创建和插入域类(使用自定义方言为每个表创建一个序列,但我认为这无关紧要)。现在,在某些情况下,我想选择自己的 ID 进行插入。
我想象两种基本方式:
- 首选:只需在保存之前在域中设置 id。如果未设置,则使用生成的 id。我天真地尝试了这个,但它没有用,即插入实例时使用自动生成的 id,即使域实例中已经设置了另一个 id。
- 使用“生成器:分配”映射并确定默认 ID(让数据库决定)。如何做到这一点最好?
场景:使用默认的 Postgres 序列生成器创建和插入域类(使用自定义方言为每个表创建一个序列,但我认为这无关紧要)。现在,在某些情况下,我想选择自己的 ID 进行插入。
我想象两种基本方式:
好的,所以最后我想出了这个(基本上是其他人在不同时间点提出的各种建议的组合)
package org.hibernate.id;
import java.io.Serializable;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.Type;
public class UseExistingOrGenerateTabelNameSequenceIdGenerator extends org.hibernate.id.enhanced.SequenceStyleGenerator {
/**
* {@inheritDoc} If the instance to insert does contain an ID
* we use that id instead of an auto generated one.
*/
@Override
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
Serializable id = session.getEntityPersister(null, object).getClassMetadata().getIdentifier(object, session);
return id != null ? id : super.generate(session, object);
}
/**
* {@inheritDoc} If the parameters do not contain a
* {@link SequenceStyleGenerator#SEQUENCE_PARAM} name, we assign one based on the
* table name.
*/
@Override
public void configure(final Type type, final Properties params, final Dialect dialect) {
if (params.getProperty(SEQUENCE_PARAM) == null || params.getProperty(SEQUENCE_PARAM).length() == 0) {
String tableName = params.getProperty(PersistentIdentifierGenerator.TABLE);
if (tableName != null) {
params.setProperty(SEQUENCE_PARAM, "seq_" + tableName);
}
}
super.configure(type, params, dialect);
}
}
要专门在域类上使用它,您将包括类似
static mapping = {
id generator:'org.hibernate.id.UseExistingOrGenerateTabelNameSequenceIdGenerator', params:[optimizer:'pooled', increment_size:10]
}
到您的域类定义中,它还允许指定一个 id 池及其大小。到目前为止似乎运行良好:)