如何用Hibernate实现一个自定义的String序列标识符生成器 [英] How to implement a custom String sequence identifier generator with Hibernate
问题描述
我在spring中使用hibernate,h2和liquibase,我试图通过以博文但是我得到一个错误:引起:org.hibernate.id.IdentifierGenerationException:ids的未知整数数据类型:java.lang.String
这里是我的SequenceStyleGenerator代码:
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;
}
}
返回CTC+ super.generate(session,obj);
$ / code>
我的实体代码:
@Entity
@Table(name =contact)
public class Contact实现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;
<?xml version =1.0encoding =utf-8?>
< databaseChangeLog
xmlns =http://www.liquibase.org/xml/ns/dbchangelog
xmlns:xsi =http://www.w3.org/2001 / XMLSchema-instance
xsi:schemaLocation =http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd >
< changeSet id =20160513091901-1author =jhipster>
< createTable tableName =contact>
< column name =idtype =longvarcharautoIncrement =$ {autoIncrement}>
< constraints primaryKey =truenullable =false/>
< / column>
< / changeSet>
< / databaseChangeLog>
顺便说一句,有可能避免参数sequence_name,因此hibernate可以自己处理这个参数吗?
如果有人可以帮助我,谢谢!
问题在于 SequenceStyleGenerator
期望返回一个数值,而不是 String
。
我已经尝试 a这个问题的解决方案,它像一个魅力。因此,您需要更改您的生成器,如下所示:
public class StringSequenceIdentifier implements IdentifierGenerator,Configurable {
private String sequenceCallSyntax;
$ b @Override
public void configure(Type params,ServiceRegistry serviceRegistry)throws MappingException {
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService(JdbcEnvironment.class);
final方言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));
$ b @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 );
返回CTC+ seqValue;
$ / code $ / pre
$ b $ p您的映射变为:
@Entity(name =Post)
@Table(name =post)
public static class Post implements Identifiable<串GT; {
@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)
私人字符串ID;
@版本
私人整数版本;
$ b $ public Post(){
}
public Post(String id){
this.id = id;
}
@Override
public String getId(){
return id;
现在,当您插入以下实体时: p>
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 ,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 。
I'm using hibernate with spring, h2 and liquibase and I'm trying to make a custom String id generator for my entities by taking example with this blog post but I'm getting an error : Caused by: org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.String
Here my SequenceStyleGenerator code :
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);
}
}
My entity code :
@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;
}
}
And the liquibase XML :
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<property name="autoIncrement" value="true" dbms="mysql,h2,postgresql,oracle"/>
<property name="floatType" value="float4" dbms="postgresql, h2"/>
<property name="floatType" value="float" dbms="mysql, oracle"/>
<changeSet id="20160513091901-1" author="jhipster">
<createTable tableName="contact">
<column name="id" type="longvarchar" autoIncrement="${autoIncrement}">
<constraints primaryKey="true" nullable="false"/>
</column>
</changeSet>
</databaseChangeLog>
Btw is it possible to avoid the parameter sequence_name so hibernate can handle this by itself ?
If anyone can help me, Thanks !
The problem is that SequenceStyleGenerator
expects to return a numerical value, not a String
.
I already tried a solution for this problem and it works like a charm. Therefore, you need to change your generator like this:
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;
}
}
Your mapping becomes:
@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;
}
}
Now, when you insert the following entities:
doInJPA(entityManager -> {
entityManager.persist(new Post());
entityManager.persist(new Post("ABC"));
entityManager.persist(new Post());
entityManager.persist(new Post("DEF"));
});
Hibernate generates the right identifier:
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)]
Code available on GitHub.
这篇关于如何用Hibernate实现一个自定义的String序列标识符生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!