2016-06-10 16 views
4

Ich benutze Hibernate mit Spring, h2 und Liquibase und ich versuche, einen benutzerdefinierten String-ID-Generator für meine Entitäten, indem Sie Beispiel mit dieser blog post, aber ich bin einen Fehler bekommen: Caused by: org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.StringWie Implementieren eines benutzerdefinierten String Sequence Identifier-Generator mit Hibernate

Hier mein 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); 
    } 
} 

Meine Einheit 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; 
    } 
} 

Und die 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 ist es möglich, die Parameter sequence_name so überwintern verarbeiten kann dies allein zu vermeiden?

Wenn mir jemand helfen kann, Danke!

+0

Ähnliche Diskussion ist passiert bei: http://StackOverflow.com/A/15470272/2128503 – Mamun

Antwort

6

Das Problem ist, dass SequenceStyleGenerator erwartet, einen numerischen Wert, nicht String zurückgeben.

Ich habe bereits versucht a solution for this problem and it works like a charm. Daher müssen Sie Ihren Generator wie folgt ändern:

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; 
    } 
} 

Ihre Mapping wird:

@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; 
    } 
} 

Nun, wenn Sie die folgenden Einheiten ein:

doInJPA(entityManager -> { 
    entityManager.persist(new Post()); 
    entityManager.persist(new Post("ABC")); 
    entityManager.persist(new Post()); 
    entityManager.persist(new Post("DEF")); 
}); 

Hibernate erzeugt die richtige Kennung :

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 verfügbar unter GitHub.

-1

Ja, Hibernate haben vorgefertigte String-Generatoren. Ersetzen Sie einfach Ihre @GenericGenerator Definition durch eine andere Strategie.

@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; 
    } 
} 

Weitere Informationen zu den verschiedenen Hibernate Generatoren Sie bei documentation aussehen kann.

+0

Ok, aber ich versuche, eine benutzerdefinierte String ID Generator für Ids wie "CTC00001", CTC00002 "... etc ohne den Parameter sequence_name :) – Takmashido