如何使用PREFIX实现IdentifierGenerator并为每个实体分隔Sequence

时间:2018-02-11 21:43:47

标签: hibernate jpa hibernate-mapping

我已经按照基本的弗拉德指南来实现前缀发生器,但是遇到了问题。

目标是同时:

  1. 每个实体的单独序列
  2. 我通过注释定义的前缀(我猜是@GenericGenerator
  3. 使用hibernate.hbm2ddl.auto=create在每个应用重启(重新部署,无论......)时删除并创建所有序列。
  4. 能够在PACKAGE级别设置前缀,而不仅仅是在class / id-field
  5. 如何同时实施这些条件?

    THE(PARTIAL!)解决方案

    我设法用这个部分解决了这个任务:

    @GenericGenerator(
        name = "prefix-sequence",
        strategy = "soberich.utils.StringSequenceIdentifier",
        parameters = {
                @Parameter(name="prefer_sequence_per_entity", value="true"),
                @Parameter(name = SEQUENCE_PREFIX, value = "A-")})
    
    每个class / id-field

    上的

    和下面的代码片段实现了生成器策略。

    import org.hibernate.HibernateException;
    import org.hibernate.MappingException;
    import org.hibernate.Session;
    import org.hibernate.dialect.Dialect;
    import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
    import org.hibernate.engine.spi.SharedSessionContractImplementor;
    import org.hibernate.id.Configurable;
    import org.hibernate.id.IdentifierGenerator;
    import org.hibernate.service.ServiceRegistry;
    import org.hibernate.type.Type;
    
    import javax.persistence.PersistenceException;
    import java.io.Serializable;
    import java.util.Properties;
    
    import static java.lang.String.format;
    import static java.lang.String.join;
    import static org.hibernate.id.enhanced.SequenceStyleGenerator.*;
    import static org.hibernate.internal.util.config.ConfigurationHelper.*;
    
    public class StringSequenceIdentifier implements IdentifierGenerator, Configurable {
        public static final String SEQUENCE_PREFIX = "sequence_prefix"; 
        private String sequencePrefix;
        private String sequenceCallSyntax;
        @Override
        public void configure(final Type type,
                              final Properties params,
                              final ServiceRegistry serviceRegistry) throws MappingException {
            final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService(JdbcEnvironment.class);
            final Dialect dialect = jdbcEnvironment.getDialect();
            sequencePrefix = getString(SEQUENCE_PREFIX, params, "SEQ_");
            final String sequencePerEntitySuffix =
                    getString(CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, params, DEF_SEQUENCE_SUFFIX);
            final String defaultSequenceName =
                    getBoolean(CONFIG_PREFER_SEQUENCE_PER_ENTITY, params, false)
                            ? params.getProperty(JPA_ENTITY_NAME) + sequencePerEntitySuffix
                            : DEF_SEQUENCE_NAME;
            sequenceCallSyntax =
                    dialect.getSequenceNextValString(getString(SEQUENCE_PARAM, params, defaultSequenceName));
        }
        @Override
        public Serializable generate(final SharedSessionContractImplementor session,
                                     final Object object) throws HibernateException {
            final long seqValue = ((Number) Session.class.cast(session)
                    .createNativeQuery(sequenceCallSyntax)
                    .uniqueResult()).longValue();
            return sequencePrefix + format("%011d", seqValue);
        }
    }
    

    问题左侧

    1. 创建和删除了错误的序列。系统创建名称为
    2. 的序列

      " Entity_SEQ" - 自动生成

      并在重启后丢弃它们,但是

      entity_seq - 小写序列是用于nextval('entity_seq')的真实序列。因此,您应该在重新启动期间手动创建它们,而drop阶段异常将像"..relation "entity_seq" does not exist"一样抛出。所以,基本上它不能自动工作。你必须创建序列!

      感觉应该有一个非常简单的解决方案。

      1. 所以,尽管这种解决方案有点有效(即使" buggy")PACKAGE级别注释不起作用。它尝试创建名为"prefix-sequence"的序列,该序列是@GenericGenerator上的名称。如果相反@Parameter(name="prefer_sequence_per_entity", value="true")我将@Parameter(name = "sequence_name", value = "entity_seq")放在class / id-field上,我不明白为什么会发生完全相同的事。

0 个答案:

没有答案