簡體   English   中英

JPA 或 Hibernate 生成(非主鍵)列值,而不是從 1 開始

[英]JPA or Hibernate to generate a (non primary key) column value, not starting from 1

我想要一個可以生成列值的 JPA/Hibernate(最好是 JPA)注釋,它不是主鍵,也不是從 1 開始。

從我所看到的 JPA 不能用 @GeneratedValue 和 @SequenceGenerator 和 @TableGenerator 做到這一點。 或與其他任何東西。

我見過一個帶有額外桌子的解決方案,我發現它並不優雅。

我可以接受 Hibernate 注釋,因為我已經有了 Hibernate 注釋。

我想使用 @Generated 但我無法讓它工作,人們聲稱這是可能的。

@Generated(GenerationTime.INSERT)
private long invoiceNumber;//invoice number

更新:一個額外的要求,如果事務回滾,我們不能在編號上有間隙。 任何人?

@GeneratedValue僅適用於標識符,因此您不能使用它。 如果您使用 MySQL,您將受到很大限制,因為不支持數據庫序列。

InnoDB 不支持多個 AUTO_INCREMENT 列,如果您的表 PK 是 AUTO_INCREMENTED,那么您有兩個選擇:

  1. 尋找一個單獨的表,它的行為類似於序列生成器,這是您已經說過不滿意的解決方案。

  2. 使用INSERT TRIGGER增加該列。

這對我有用 - 我們在服務中編碼了所有這些。 這是實體:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Registrant extends AbstractEntity {
    //....
    private long invoiceNumber;//invoice number

    @Entity
    public static class InvoiceNumberGenerator {
        @Id
        @GeneratedValue
        private int id;
        private long counter;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public long getCounter() {
            return counter;
        }

        public void setCounter(long counter) {
            this.counter = counter;
        }
    }
}

然后我們有一個服務可以施展魔法(實際上沒有魔法,一切都是手動完成的):

public synchronized Registrant save(Registrant registrant) {
    long counter = getInvoiceNumber();
    registrant.setInvoiceNumber(counter);

    return registrantRepository.save(registrant);
}

private long getInvoiceNumber() {
    //mist: get the invoice number from the other table
    long count = registrantInvoiceNumberGeneratorRepository.count();
    if(count > 1) {
        throw new RuntimeException(": InvoiceNumberGenerator table has more than one row. Fix that");
    }

    Registrant.InvoiceNumberGenerator generator;
    if(count == 0) {
        generator = new Registrant.InvoiceNumberGenerator();
        generator.setCounter(1000001);
        generator = registrantInvoiceNumberGeneratorRepository.save(generator);
    } else {
        generator = registrantInvoiceNumberGeneratorRepository.findFirstByOrderByIdAsc();
    }


    long counter = generator.getCounter();
    generator.setCounter(counter+1);
    registrantInvoiceNumberGeneratorRepository.save(generator);
    return counter;
}

注意synchronized方法 - 這樣沒有人可以獲得相同的數字。

我不敢相信沒有什么自動可以做到這一點。

與@Vlad Mihalcea 相關,現在您可以使用@GeneratorType 為非 id 列生成您自己的自定義值。 例如:

  1. 實體:
    import org.hibernate.annotations.GeneratorType

    @GeneratorType(type = CustomGenerator.class, when = GenerationTime.INSERT)
    @Column(name = "CUSTOM_COLUMN", unique = true, nullable = false, updatable = false, lenght = 64)
    private String custom;
  1. 值生成器實現:
public class CustomGenerator extends ValueGenerator<String> {
        private static final String TODAY_EXAMPLE_QUERY = "from Example where createDate>:start and createDate<:end order by createDate desc";
        private static final String START_PARAMETER = "start";
        private static final String END_PARAMETER = "end";
        private static final String NEXTVAL_QUERY = "select EXAMPLE_SEQ.nextval from dual";
        private final SimpleDateFormat dataFormat = new SimpleDateFormat("yyyyMMdd");

        @Override
        public String generateValue(Session session, Object owner) {
            Date now = new Date();
            Query<Example> todayQuery = session.createQuery(TODAY_EXAMPLE_QUERY, Example.class);
            query.setParameter(START_PARAMETER, start(now));
            query.setParameter(END_PARAMETER, end(now));
            Example lastExample = todayQuery.setMaxResult(1).setHibernateFlushMode(COMMIT).uniqueResult();

            NativeQuery nextvalQuery = session.createSQLQuery(NEXTVAL_QUERY);
            Number nextvalValue = nextvalQuery.setFlushMode(COMMIT).uniqueResult();
            return dataFormat.format(now) + someParameter(lastExample) + nextvalValue.longValue();
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM