9
public class SequenceControlNumber extends SequenceGenerator {

    private static final Logger log =
        LoggerFactory.getLogger(SequenceGenerator.class);

    @Override
    public Serializable generate(SessionImplementor session, Object obj) {
        Connection connection = session.connection();
        try {
            PreparedStatement st = connection.prepareStatement
                   ("SELECT nextval ('sequencecontrolnumber') as nextval");
            try {
                ResultSet rs = st.executeQuery();
                try {
                    rs.next();
                    int currentVall = rs.getInt("sequencecontrolnumber");
                    int result = 0;
                    if(currentVall <255){
                        result = currentVall +1;
                    }
                    if ( log.isDebugEnabled() ) {
                        log.debug("Sequence identifier generated: " + result);
                    }
                    return result;
                }
                finally {
                    rs.close();
                }
            }
            finally {
                session.getBatcher().closeStatement(st);
            }
        }
        catch (SQLException sqle) {
            throw JDBCExceptionHelper.convert(
                    session.getFactory().getSQLExceptionConverter(),
                    sqle,"could not get next sequence value");
        }
    }

}

私のモデルクラスでは、これは私の注釈です。

@GenericGenerator(name="seq_id",
        strategy="br.com.otgmobile.service.dao.SequenceControlNumber")
@GeneratedValue(generator="seq_id")
@Column(name="sequencecontrolnumber",unique=false, nullable=false)
private Integer sequenceControlNumber;

しかし、プロパティ値の例外が発生し続けます。

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: br.com.otgmobile.model.niagarahw06.ComandoNiagaraHw06.sequenceControlNumber
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1179)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1112)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1118)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:618)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at $Proxy33.persist(Unknown Source)
at br.com.otgmobile.service.dao.ComandoNiagaraHw06DAO.add(ComandoNiagaraHw06DAO.java:57)
at br.com.otgmobile.service.dao.ComandoNiagaraHw06DAO$$FastClassByCGLIB$$e19cf51d.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at br.com.otgmobile.service.dao.ComandoNiagaraHw06DAO$$EnhancerByCGLIB$$69ccb4e4.add(<generated>)
at br.com.otgmobile.server.NiagaraSocketManager.testPersistComandos(NiagaraSocketManager.java:100)
at br.com.otgmobile.server.NiagaraSocketManager.start(NiagaraSocketManager.java:45)
at br.com.otgmobile.server.NiagaraDaemon.run(NiagaraDaemon.java:25)
at java.lang.Thread.run(Thread.java:722)

Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: br.com.otgmobile.model.niagarahw06.ComandoNiagaraHw06.sequenceControlNumber
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:101)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:800)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:774)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:778)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:612)
4

5 に答える 5

4

非IDフィールドのカスタムシーケンスジェネレーターの場合、ValueGeneratorクラスの実装で@GeneratorTypeを使用できます。例えば:

  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. ValueGeneratorの実装:
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);
            todayQuery.setParameter(START_PARAMETER, start(now));
            todayQuery.setParameter(END_PARAMETER, end(now));
            Example todayLastExample = todayQuery.setMaxResult(1).setHibernateFlushMode(COMMIT).uniqueResult();

            NativeQuery nextvalQuery = session.createSQLQuery(NEXTVAL_QUERY);
            Number nextvalValue = nextvalQuery.setFlushMode(COMMIT).uniqueResult();
            return dataFormat.format(now) + someParameter(todayLastExample) + nextvalValue.longValue();
        }
    }
于 2020-06-10T17:50:53.637 に答える
2

注釈は、@GeneratedValueHibernateが列の情報の一部として処理するものではありません。@Id注釈と組み合わせて使用​​する必要があります。IDがある場合にIDがどのように生成されるかを示しているだけです。

やりたいことを達成するためのいくつかのオプションがありますが、あなたが書いたような注釈を使用するほどエレガントなものはありません。これらの提案には長所と短所(データベースの移植性、複雑さ、エンティティマネージャーとセッションなど)がありますが、いくつかのアイデアは次のとおりです。

  • PreInsertListenerを実装し、それをに追加しますAnnotationConfiguration。このリスナーは、この機能を必要とするエンティティのタイプを探し、次のシーケンス値を取得/割り当てます
  • シーケンス値の列への入力を処理するデータベーストリガーを作成します。Javaコードの列を次のようにマークしますinsertable = false, updatable = false
  • 生成ロジックをエンティティのコールバックメソッドに配置し、@PrePersistアノテーションでマークします
  • コンストラクターの一部としてフィールドにデータを入力します(コンストラクターでDB呼び出しがあり、トランザクション境界があいまいになる可能性があるため、好ましくありません)
于 2012-09-19T14:53:14.703 に答える
2

これは少なくともPostgresでは機能します

@Generated(GenerationTime.INSERT)
@Column(name = "internal_id", columnDefinition = "serial", updatable = false)
private int internalId;
于 2020-09-01T13:30:03.220 に答える
1

クラスresultのgenerateメソッドから返されたの値を確認してください。SequenceControlNumber

ところで、このSOの質問でこの応答を確認してください:Hibernate JPAシーケンス(非ID)

于 2012-09-19T13:55:23.527 に答える
1

シーケンスを作成して主キーではないフィールドにアタッチする必要があるという同様の問題に直面しました。

Webで述べられているように、:Hibernateエンティティフィールドの@Idアノテーションに沿ってのみ使用できるため@GeneratedValue、アノテーションの使用に苦労していました。これは、フィールドがnullであることを気にしないようにHibernateに指示します。これは、データベースへの挿入時に管理されます。ただし、ここでは、GeneratedValueがフィールドで無視されたため、Hibernateは常に例外をスローしていました。@SequenceGenerator@GeneratedValue

したがって、解決策は簡単です。この注釈をに置き換え@Generated(GenerationTime.INSERT)columnDefinition = "serial"@Column(name = "huhu", columnDefinition = "serial", updatable = false, ...)

そもそもデータベースのフィールドに添付された正しいシーケンスを作成していれば、通常は機能するはずです。

于 2019-04-11T16:22:35.160 に答える