我正在使用带有spring,h2和liquibase的hibernate,我试图通过这个blog post的示例为我的实体创建一个自定义String id生成器,但是我收到一个错误:{{1 }}
这里是我的SequenceStyleGenerator代码:
Caused by: org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.String
我的实体代码:
public class CTCIDGenerator extends SequenceStyleGenerator {
@Override
public Serializable generate(SessionImplementor session, Object obj) {
if (obj instanceof Identifiable) {
Identifiable identifiable = (Identifiable) obj;
Serializable id = identifiable.getId();
if (id != null) {
return id;
}
}
return "CTC"+super.generate(session, obj);
}
}
liquibase XML:
@Entity
@Table(name = "contact")
public class Contact implements Serializable, Identifiable<String> {
private static final long serialVersionUID = 1L;
@Id
@GenericGenerator(
name = "assigned-sequence",
strategy = "net.atos.seirich.support.domain.idgenerator.CTCIDGenerator",
parameters = @org.hibernate.annotations.Parameter(
name = "sequence_name",
value = "hibernate_sequence"
)
)
@GeneratedValue(generator = "assigned-sequence", strategy = GenerationType.SEQUENCE)
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
顺便说一句,是否有可能避免参数sequence_name,所以hibernate可以单独处理它?</ p>
如果有人可以帮助我,谢谢!
答案 0 :(得分:9)
问题是SequenceStyleGenerator
期望返回一个数值,而不是String
。
我已经尝试a solution for this problem and it works like a charm了。因此,您需要像这样更改您的生成器:
public class StringSequenceIdentifier implements IdentifierGenerator, Configurable {
private String sequenceCallSyntax;
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService(JdbcEnvironment.class);
final Dialect dialect = jdbcEnvironment.getDialect();
final String sequencePerEntitySuffix = ConfigurationHelper.getString(CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, params, DEF_SEQUENCE_SUFFIX);
final String defaultSequenceName = ConfigurationHelper.getBoolean(CONFIG_PREFER_SEQUENCE_PER_ENTITY, params, false)
? params.getProperty(JPA_ENTITY_NAME) + sequencePerEntitySuffix
: DEF_SEQUENCE_NAME;
sequenceCallSyntax = dialect.getSequenceNextValString(ConfigurationHelper.getString(SEQUENCE_PARAM, params, defaultSequenceName));
}
@Override
public Serializable generate(SessionImplementor session, Object obj) {
if (obj instanceof Identifiable) {
Identifiable identifiable = (Identifiable) obj;
Serializable id = identifiable.getId();
if (id != null) {
return id;
}
}
long seqValue = ((Number) Session.class.cast(session)
.createSQLQuery(sequenceCallSyntax)
.uniqueResult()).longValue();
return "CTC" + seqValue;
}
}
您的映射变为:
@Entity(name = "Post")
@Table(name = "post")
public static class Post implements Identifiable<String> {
@Id
@GenericGenerator(
name = "assigned-sequence",
strategy = "com.vladmihalcea.book.hpjp.hibernate.identifier.StringSequenceIdentifier",
parameters = @org.hibernate.annotations.Parameter(name = "sequence_name", value = "hibernate_sequence")
)
@GeneratedValue(generator = "assigned-sequence", strategy = GenerationType.SEQUENCE)
private String id;
@Version
private Integer version;
public Post() {
}
public Post(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
}
现在,当您插入以下实体时:
doInJPA(entityManager -> {
entityManager.persist(new Post());
entityManager.persist(new Post("ABC"));
entityManager.persist(new Post());
entityManager.persist(new Post("DEF"));
});
Hibernate生成正确的标识符:
Query:["select nextval ('hibernate_sequence')"], Params:[()]
Query:["select nextval ('hibernate_sequence')"], Params:[()]
Query:["insert into post (version, id) values (?, ?)"], Params:[(0, CTC1)]
Query:["insert into post (version, id) values (?, ?)"], Params:[(0, ABC)]
Query:["insert into post (version, id) values (?, ?)"], Params:[(0, CTC2)]
Query:["insert into post (version, id) values (?, ?)"], Params:[(0, DEF)]
GitHub上提供的代码。
答案 1 :(得分:0)
是的,hibernate有预构建的String生成器。只需将您的@GenericGenerator
定义替换为另一种策略。
@Entity
@Table(name = "contact")
public class Contact implements Serializable, Identifiable<String> {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
有关不同hibernate生成器的更多信息,请查看documentation。