최대 절전 모드 JPA 시퀀스 (비 ID)


138

식별자가 아니거나 복합 식별자의 일부가 아닌 일부 열에 DB 시퀀스를 사용할 수 있습니까?

나는 최대 절전 모드를 jpa 공급자로 사용하고 있으며 식별자의 일부는 아니지만 값을 생성하는 (시퀀스를 사용하여) 일부 열이있는 테이블이 있습니다.

내가 원하는 것은 시퀀스를 사용하여 엔티티의 새 값을 만드는 것입니다. 시퀀스의 열 이 기본 키 가 아닙니다 (일부 키).

@Entity
@Table(name = "MyTable")
public class MyEntity {

    //...
    @Id //... etc
    public Long getId() {
        return id;
    }

   //note NO @Id here! but this doesn't work...
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "myGen")
    @SequenceGenerator(name = "myGen", sequenceName = "MY_SEQUENCE")
    @Column(name = "SEQ_VAL", unique = false, nullable = false, insertable = true, updatable = true)
    public Long getMySequencedValue(){
      return myVal;
    }

}

그런 다음 내가 할 때 :

em.persist(new MyEntity());

ID는 생성되지만 mySequenceValJPA 제공 업체에서도 속성을 생성합니다.

분명히하기 위해 : HibernatemySequencedValue속성 의 값을 생성하기를 원합니다 . Hibernate가 데이터베이스 생성 값을 처리 할 수 ​​있다는 것을 알고 있지만, 트리거나 Hibernate 이외의 다른 것을 사용하여 내 속성 값을 생성하고 싶지 않습니다. 최대 절전 모드에서 기본 키에 대한 값을 생성 할 수 있다면 간단한 속성에 대해 생성 할 수없는 이유는 무엇입니까?

답변:


77

이 문제에 대한 답을 찾고이 링크를 우연히 발견했습니다.

Hibernate / JPA가 비 ID 속성 값을 자동으로 생성 할 수없는 것 같습니다. @GeneratedValue과 주석 만 함께 사용됩니다 @Id자동으로 번호를 만들 수 있습니다.

@GeneratedValue주석은 데이터베이스가이 값 자체를 생성하는 것을 Hibernate에게 알려준다.

이 포럼에서 제안 된 솔루션 (또는 해결 방법)은 다음과 같이 생성 된 ID로 별도의 엔터티를 만드는 것입니다.

@실재
공개 클래스 GeneralSequenceNumber {
  @신분증
  @GeneratedValue (...)
  개인용 긴 번호;
}

@실재 
공개 클래스 MyEntity {
  @ 아이디 ..
  개인 롱 ID;

  @1-1(...)
  개인 GeneralSequnceNumber myVal;
}

@GeneratedValue의 Java 문서에서 : "GeneratedValue 주석은 엔티티의 기본 키 특성 또는 필드 또는 ID 주석과 함께 맵핑 된 수퍼 클래스에 적용될 수 있습니다"
Kariem

11
@Column (columnDefinition = "serial")이 완벽하게 작동하지만 PostgreSQL에서만 작동한다는 것을 알았습니다. 나를 위해 이것은 완벽한 솔루션이었습니다. 왜냐하면 두 번째 엔터티는 "추악한"옵션이기 때문입니다
Sergey Vedernikov

@SergeyVedernikov 매우 도움이되었습니다. 별도의 답변으로 게시 하시겠습니까? 내 문제를 매우 간단하고 효과적으로 해결했습니다.
매트 볼

@MattBall 나는 이것을 별도의 답변으로 게시했습니다 :) stackoverflow.com/a/10647933/620858
Sergey Vedernikov

1
@GeneratedValueID가 아닌 필드 를 허용하는 제안을 열었습니다 . 2.2에 포함되는 투표하세요 java.net/jira/browse/JPA_SPEC-113
페 타르 Tahchiev

44

나는 그것이 @Column(columnDefinition="serial")PostgreSQL에 대해서만 완벽하게 작동 한다는 것을 알았습니다 . 나에게 이것은 완벽한 해결책이었습니다. 왜냐하면 두 번째 엔터티는 "못생긴"옵션이기 때문입니다.


안녕하세요, 설명이 필요합니다. 좀 더 말씀해 주시겠습니까?
Emaborsa

2
@Emaborsa이 columnDefinition=비트는 기본적으로 Hiberate에게 열 정의를 생성하지 말고 대신 제공 한 텍스트를 사용하도록 지시합니다. 기본적으로 열에 대한 DDL은 문자 그대로 name + columnDefinition입니다. 이 경우 (PostgreSQL) mycolumn serial은 테이블의 유효한 열입니다.
Patrick

7
MySQL을위한 등가이다@Column(columnDefinition = "integer auto_increment")
리처드 켄 나드

2
이 자동 값을 생성합니까? 이와 같은 필드 정의로 엔티티를 유지하려고 시도했지만 값을 생성하지 않았습니다. <column> 열에 null 값을 입력하여 null이 아닌 제약 조건을 위반했습니다
KyelJmD

7
내가 사용 @Column(insertable = false, updatable = false, columnDefinition="serial")널 값을 삽입하려고하거나 필드를 업데이트 최대 절전 모드 방지 할 수 있습니다. 그런 다음 바로 사용해야하는 경우 삽입 후 생성 된 ID를 얻으려면 db를 다시 쿼리해야합니다.
Robert Di Paolo

20

나는 이것이 매우 오래된 질문이라는 것을 알고 있지만 첫 번째 결과에 표시되었으며 jpa는 질문 이후 많은 변화를 겪었습니다.

지금 올바른 방법은 @Generated주석을 사용하는 것입니다. 시퀀스를 정의하고 열의 기본값을 해당 시퀀스로 설정 한 다음 열을 다음과 같이 매핑 할 수 있습니다.

@Generated(GenerationTime.INSERT)
@Column(name = "column_name", insertable = false)

1
그래도 데이터베이스에서 값을 생성해야하므로 질문에 실제로 대답하지는 않습니다. 12c 이전의 Oracle 데이터베이스의 경우 값을 생성하려면 데이터베이스 트리거를 작성해야합니다.
Bernie

9
또한 이것은 JPA가 아닌 Hibernate 주석입니다.
caarlos0

14

최대 절전 모드가이를 지원합니다. 문서에서 :

"생성 된 속성은 데이터베이스에서 값을 생성 한 속성입니다. 일반적으로 Hibernate 응용 프로그램은 데이터베이스가 값을 생성 한 속성이 포함 된 개체를 새로 고쳐야했습니다. 그러나 속성을 생성 된 것으로 표시하면 응용 프로그램에서이 책임을 Hibernate에 위임 할 수 있습니다. 기본적으로, Hibernate는 생성 된 속성을 정의한 엔티티에 대해 SQL INSERT 또는 UPDATE를 발행 할 때마다 생성 된 값을 검색하기 위해 즉시 선택을 발행합니다. "

삽입시에만 생성 된 속성의 경우 속성 매핑 (.hbm.xml)은 다음과 같습니다.

<property name="foo" generated="insert"/>

삽입 및 업데이트시 생성되는 속성의 경우 속성 매핑 (.hbm.xml)은 다음과 같습니다.

<property name="foo" generated="always"/>

불행히도 JPA를 모르므 로이 기능이 JPA를 통해 노출되는지 알 수 없습니다 (아마 의심되지 않습니다)

또는 삽입 및 업데이트에서 속성을 제외한 다음 "수동으로"call session.refresh (obj); 삽입 / 업데이트 한 후 데이터베이스에서 생성 된 값을로드하십시오.

다음은 insert 및 update 문에서 속성이 사용되지 않도록하는 방법입니다.

<property name="foo" update="false" insert="false"/>

다시 한 번, JPA가 이러한 최대 절전 기능을 제공하는지 여부는 알 수 없지만 최대 절전 기능은이를 지원합니다.


1
@Generated 주석은 위의 XML 구성에 해당합니다. 자세한 내용 은 최대 절전 모드 문서의이 섹션 을 참조하십시오.
Eric

8

후속 조치로 다음과 같이 작동합니다.

@Override public Long getNextExternalId() {
    BigDecimal seq =
        (BigDecimal)((List)em.createNativeQuery("select col_msd_external_id_seq.nextval from dual").getResultList()).get(0);
    return seq.longValue();
}

최대 절전 모드 4.2.19 및 oracle의 변형 : SQLQuery sqlQuery = getSession().createSQLQuery("select NAMED_SEQ.nextval seq from dual"); sqlQuery.addScalar("seq", LongType.INSTANCE); return (Long) sqlQuery.uniqueResult();
Aaron

6

@PrePersist주석을 사용하여 Hibernate로 UUID (또는 시퀀스) 생성을 수정했습니다 .

@PrePersist
public void initializeUUID() {
    if (uuid == null) {
        uuid = UUID.randomUUID().toString();
    }
}

5

이것은 오래된 스레드이지만 솔루션을 공유하고 이에 대한 의견을 얻고 싶습니다. 일부 JUnit 테스트 케이스에서 로컬 데이터베이스로만이 솔루션을 테스트했음을 경고합니다. 따라서 이것은 지금까지 생산적인 기능이 아닙니다.

속성이없는 Sequence라는 사용자 지정 주석을 도입 하여이 문제를 해결했습니다. 증분 시퀀스에서 값을 할당해야하는 필드의 마커 일뿐입니다.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sequence
{
}

이 주석을 사용하여 엔티티를 표시했습니다.

public class Area extends BaseEntity implements ClientAware, IssuerAware
{
    @Column(name = "areaNumber", updatable = false)
    @Sequence
    private Integer areaNumber;
....
}

데이터베이스를 독립적으로 유지하기 위해 시퀀스 현재 값과 증분 크기를 보유하는 SequenceNumber라는 엔티티를 소개했습니다. className을 고유 키로 선택하여 각 엔티티 클래스가 자체 시퀀스를 얻습니다.

@Entity
@Table(name = "SequenceNumber", uniqueConstraints = { @UniqueConstraint(columnNames = { "className" }) })
public class SequenceNumber
{
    @Id
    @Column(name = "className", updatable = false)
    private String className;

    @Column(name = "nextValue")
    private Integer nextValue = 1;

    @Column(name = "incrementValue")
    private Integer incrementValue = 10;

    ... some getters and setters ....
}

마지막 단계와 가장 어려운 단계는 시퀀스 번호 할당을 처리하는 PreInsertListener입니다. 스프링을 빈 컨테이너로 사용했습니다.

@Component
public class SequenceListener implements PreInsertEventListener
{
    private static final long serialVersionUID = 7946581162328559098L;
    private final static Logger log = Logger.getLogger(SequenceListener.class);

    @Autowired
    private SessionFactoryImplementor sessionFactoryImpl;

    private final Map<String, CacheEntry> cache = new HashMap<>();

    @PostConstruct
    public void selfRegister()
    {
        // As you might expect, an EventListenerRegistry is the place with which event listeners are registered
        // It is a service so we look it up using the service registry
        final EventListenerRegistry eventListenerRegistry = sessionFactoryImpl.getServiceRegistry().getService(EventListenerRegistry.class);

        // add the listener to the end of the listener chain
        eventListenerRegistry.appendListeners(EventType.PRE_INSERT, this);
    }

    @Override
    public boolean onPreInsert(PreInsertEvent p_event)
    {
        updateSequenceValue(p_event.getEntity(), p_event.getState(), p_event.getPersister().getPropertyNames());

        return false;
    }

    private void updateSequenceValue(Object p_entity, Object[] p_state, String[] p_propertyNames)
    {
        try
        {
            List<Field> fields = ReflectUtil.getFields(p_entity.getClass(), null, Sequence.class);

            if (!fields.isEmpty())
            {
                if (log.isDebugEnabled())
                {
                    log.debug("Intercepted custom sequence entity.");
                }

                for (Field field : fields)
                {
                    Integer value = getSequenceNumber(p_entity.getClass().getName());

                    field.setAccessible(true);
                    field.set(p_entity, value);
                    setPropertyState(p_state, p_propertyNames, field.getName(), value);

                    if (log.isDebugEnabled())
                    {
                        LogMF.debug(log, "Set {0} property to {1}.", new Object[] { field, value });
                    }
                }
            }
        }
        catch (Exception e)
        {
            log.error("Failed to set sequence property.", e);
        }
    }

    private Integer getSequenceNumber(String p_className)
    {
        synchronized (cache)
        {
            CacheEntry current = cache.get(p_className);

            // not in cache yet => load from database
            if ((current == null) || current.isEmpty())
            {
                boolean insert = false;
                StatelessSession session = sessionFactoryImpl.openStatelessSession();
                session.beginTransaction();

                SequenceNumber sequenceNumber = (SequenceNumber) session.get(SequenceNumber.class, p_className);

                // not in database yet => create new sequence
                if (sequenceNumber == null)
                {
                    sequenceNumber = new SequenceNumber();
                    sequenceNumber.setClassName(p_className);
                    insert = true;
                }

                current = new CacheEntry(sequenceNumber.getNextValue() + sequenceNumber.getIncrementValue(), sequenceNumber.getNextValue());
                cache.put(p_className, current);
                sequenceNumber.setNextValue(sequenceNumber.getNextValue() + sequenceNumber.getIncrementValue());

                if (insert)
                {
                    session.insert(sequenceNumber);
                }
                else
                {
                    session.update(sequenceNumber);
                }
                session.getTransaction().commit();
                session.close();
            }

            return current.next();
        }
    }

    private void setPropertyState(Object[] propertyStates, String[] propertyNames, String propertyName, Object propertyState)
    {
        for (int i = 0; i < propertyNames.length; i++)
        {
            if (propertyName.equals(propertyNames[i]))
            {
                propertyStates[i] = propertyState;
                return;
            }
        }
    }

    private static class CacheEntry
    {
        private int current;
        private final int limit;

        public CacheEntry(final int p_limit, final int p_current)
        {
            current = p_current;
            limit = p_limit;
        }

        public Integer next()
        {
            return current++;
        }

        public boolean isEmpty()
        {
            return current >= limit;
        }
    }
}

위 코드에서 알 수 있듯이 리스너는 엔티티 클래스 당 하나의 SequenceNumber 인스턴스를 사용했으며 SequenceNumber 엔티티의 incrementValue로 정의 된 두 개의 시퀀스 번호를 예약합니다. 시퀀스 번호가 부족하면 대상 클래스의 SequenceNumber 엔터티를로드하고 다음 호출에 대해 incrementalValue 값을 예약합니다. 이렇게하면 시퀀스 값이 필요할 때마다 데이터베이스를 쿼리 할 필요가 없습니다. 다음 시퀀스 번호 세트를 예약하기 위해 열려있는 StatelessSession에 유의하십시오. EntityPersister에서 ConcurrentModificationException이 발생하므로 대상 엔티티가 현재 지속되는 동일한 세션을 사용할 수 없습니다.

이것이 누군가를 돕기를 바랍니다.


5

postgresql을
사용하고 있고 스프링 부트 1.5.6을 사용하는 경우

@Column(columnDefinition = "serial")
@Generated(GenerationTime.INSERT)
private Integer orderID;

1
그것은 내가 이미 지적한 것 외에도, 봄 부팅 2.1.6.RELEASE, 최대 절전 모드 5.3.10.Final를 사용하고, 너무 나를 위해 일한, 나는 secuence 만들어야했습니다 seq_order, 필드 및 메이크업 참조 양식을 nextval('seq_order'::regclass)
OJVM

3

나는 당신과 같은 상황에서 달리고 기본적으로 JPA로 ID가 아닌 속성을 생성 할 수 있는지 여부에 대한 심각한 대답을 찾지 못했습니다.

내 솔루션은 네이티브 JPA 쿼리로 시퀀스를 호출하여 속성을 확인하기 전에 수동으로 속성을 설정하는 것입니다.

이것은 만족스럽지 않지만 현재 해결 방법으로 작동합니다.

마리오


2

세션 9.1.9에서 JPA 스펙의 GeneratedValue Annotation에서이 특정 참고 사항을 발견했습니다. "[43] 휴대용 응용 프로그램은 다른 지속적 필드 또는 특성에 GeneratedValue 주석을 사용해서는 안됩니다." 따라서 최소한 JPA를 사용하여 기본 키가 아닌 값의 값을 자동 생성하는 것이 불가능하다고 가정합니다.


1

스레드가 오래 된 것처럼 보이므로 여기에 솔루션을 추가하고 싶었습니다 (SpringJ-AOP 사용).

해결책은 @InjectSequenceValue다음과 같이 사용자 정의 주석을 작성하는 것입니다.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectSequenceValue {
    String sequencename();
}

이제 엔터티의 모든 필드에 주석을 달 수 있으므로 기본 필드 (Long / Integer) 값이 런타임시 다음 값을 사용하여 런타임에 주입됩니다.

이렇게 주석을 달아주세요.

//serialNumber will be injected dynamically, with the next value of the serialnum_sequence.
 @InjectSequenceValue(sequencename = "serialnum_sequence") 
  Long serialNumber;

지금까지 필드에 표시를하여 시퀀스 값을 주입해야하므로, 표시된 필드에 시퀀스 값을 주입하는 방법을 살펴 보겠습니다. AspectJ에서 포인트 컷을 생성하여 수행합니다.

save/persist메소드가 실행 되기 직전에 주입을 시작합니다 . 이는 아래 클래스에서 수행됩니다.

@Aspect
@Configuration
public class AspectDefinition {

    @Autowired
    JdbcTemplate jdbcTemplate;


    //@Before("execution(* org.hibernate.session.save(..))") Use this for Hibernate.(also include session.save())
    @Before("execution(* org.springframework.data.repository.CrudRepository.save(..))") //This is for JPA.
    public void generateSequence(JoinPoint joinPoint){

        Object [] aragumentList=joinPoint.getArgs(); //Getting all arguments of the save
        for (Object arg :aragumentList ) {
            if (arg.getClass().isAnnotationPresent(Entity.class)){ // getting the Entity class

                Field[] fields = arg.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(InjectSequenceValue.class)) { //getting annotated fields

                        field.setAccessible(true); 
                        try {
                            if (field.get(arg) == null){ // Setting the next value
                                String sequenceName=field.getAnnotation(InjectSequenceValue.class).sequencename();
                                long nextval=getNextValue(sequenceName);
                                System.out.println("Next value :"+nextval); //TODO remove sout.
                                field.set(arg, nextval);
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        }
    }

    /**
     * This method fetches the next value from sequence
     * @param sequence
     * @return
     */

    public long getNextValue(String sequence){
        long sequenceNextVal=0L;

        SqlRowSet sqlRowSet= jdbcTemplate.queryForRowSet("SELECT "+sequence+".NEXTVAL as value FROM DUAL");
        while (sqlRowSet.next()){
            sequenceNextVal=sqlRowSet.getLong("value");

        }
        return  sequenceNextVal;
    }
}

이제 아래와 같이 엔티티에 주석을 달 수 있습니다.

@Entity
@Table(name = "T_USER")
public class UserEntity {

    @Id
    @SequenceGenerator(sequenceName = "userid_sequence",name = "this_seq")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "this_seq")
    Long id;
    String userName;
    String password;

    @InjectSequenceValue(sequencename = "serialnum_sequence") // this will be injected at the time of saving.
    Long serialNumber;

    String name;
}

0

"트리거나 최대 절전 모드 이외의 다른 것을 사용하여 내 속성 값을 생성하고 싶지 않습니다."

이 경우 필요한 값을 생성하는 UserType 구현을 만들고 mySequenceVal 속성의 지속성을 위해 해당 UserType을 사용하도록 메타 데이터를 구성하는 방법은 무엇입니까?


0

이것은 시퀀스를 사용하는 것과 다릅니다. 시퀀스를 사용할 때는 아무 것도 삽입하거나 업데이트하지 않습니다. 다음 시퀀스 값을 검색하는 중입니다. 최대 절전 모드가 지원하지 않는 것 같습니다.


0

UNIQUEIDENTIFIER 유형의 열이 있고 삽입시 기본 생성이 필요하지만 열이 PK가 아닌 경우

@Generated(GenerationTime.INSERT)
@Column(nullable = false , columnDefinition="UNIQUEIDENTIFIER")
private String uuidValue;

db에서는

CREATE TABLE operation.Table1
(
    Id         INT IDENTITY (1,1)               NOT NULL,
    UuidValue  UNIQUEIDENTIFIER DEFAULT NEWID() NOT NULL)

이 경우 필요한 값에 대해 생성기를 정의하지 않습니다 (자동으로 감사합니다 columnDefinition="UNIQUEIDENTIFIER"). 다른 열 유형에서 시도 할 수있는 것과 동일


0

Spring 애플리케이션에서 @PostConstruct 및 JdbcTemplate을 사용하여 MySql 데이터베이스에서 이에 대한 해결 방법을 찾았습니다. 다른 데이터베이스에서도 가능하지만 제시 할 유스 케이스는 auto_increment를 사용하는 MySql에 대한 나의 경험을 기반으로합니다.

먼저 @Column 주석의 ColumnDefinition 속성을 사용하여 열을 auto_increment로 정의하려고 시도했지만 자동 증분을 수행하기 위해 열이 키가 필요했기 때문에 열이 작동하지 않았지만 열은 다음과 같이 정의되지 않았습니다. 정의 될 때까지의 색인으로 교착 상태가 발생합니다.

여기에 auto_increment 정의없이 열을 만들고 데이터베이스를 만든 추가하는 아이디어가 있습니다. @PostConstruct 어노테이션을 사용하면 JdbcTemplate의 update 메소드와 함께 애플리케이션이 Bean을 초기화 한 직후 메소드가 호출됩니다.

코드는 다음과 같습니다.

내 엔터티에서 :

@Entity
@Table(name = "MyTable", indexes = { @Index(name = "my_index", columnList = "mySequencedValue") })
public class MyEntity {
    //...
    @Column(columnDefinition = "integer unsigned", nullable = false, updatable = false, insertable = false)
    private Long mySequencedValue;
    //...
}

PostConstructComponent 클래스에서 :

@Component
public class PostConstructComponent {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @PostConstruct
    public void makeMyEntityMySequencedValueAutoIncremental() {
        jdbcTemplate.update("alter table MyTable modify mySequencedValue int unsigned auto_increment");
    }
}

0

@ Morten Berg의 승인 된 솔루션 옆에 대안을 제공하고 싶습니다.

이 방법을 사용하면 필자의 경우 유스 케이스에서 실제로 원하는 Number유형으로 필드를 정의 할 수 있습니다 . 예를 들어 JSON (직렬) 직렬화 해제에 유용 할 수 있습니다.LongGeneralSequenceNumber

단점은 약간 더 많은 데이터베이스 오버 헤드가 필요하다는 것입니다.


먼저, 우리 는 타입의 ActualEntity자동 증가 generated를 원합니다 Long:

// ...
@Entity
public class ActualEntity {

    @Id 
    // ...
    Long id;

    @Column(unique = true, updatable = false, nullable = false)
    Long generated;

    // ...

}

다음으로 헬퍼 엔티티가 필요합니다 Generated. 패키지 ActualEntity의 구현 세부 사항을 유지하기 위해 package-private를 옆에 배치했습니다 .

@Entity
class Generated {

    @Id
    @GeneratedValue(strategy = SEQUENCE, generator = "seq")
    @SequenceGenerator(name = "seq", initialValue = 1, allocationSize = 1)
    Long id;

}

마지막으로을 저장하기 전에 바로 연결할 장소가 필요합니다 ActualEntity. 여기서 Generated인스턴스를 생성하고 유지 합니다. 그런 다음 id유형 의 데이터베이스 시퀀스가 ​​생성 됩니다.Long 됩니다. 이 값을에 쓰면이 값을 사용합니다 ActualEntity.generated.

내 유스 케이스에서는 Spring Data REST 사용하여 이것을 구현 @RepositoryEventHandler했는데, ActualEntityget이 지속 되기 직전에 호출 됩니다. 다음과 같은 원리를 보여 주어야합니다.

@Component
@RepositoryEventHandler
public class ActualEntityHandler {

    @Autowired
    EntityManager entityManager;

    @Transactional
    @HandleBeforeCreate
    public void generate(ActualEntity entity) {
        Generated generated = new Generated();

        entityManager.persist(generated);
        entity.setGlobalId(generated.getId());
        entityManager.remove(generated);
    }

}

실제 응용 프로그램에서는 테스트하지 않았으므로주의해서 즐기십시오.


-1

나는 당신과 같은 상황에 있었으며 (@Id가 아닌 필드의 JPA / 최대 절전 모드 시퀀스) DB 스키마에서 삽입시 고유 시퀀스 번호를 추가하는 트리거를 만들었습니다. JPA / Hibernate와 함께 작동하는 것을 결코 얻지 못했습니다.


-1

시간을 보낸 후에 이것은 내 문제를 해결하는 데 도움이되었습니다.

Oracle 12c의 경우 :

ID NUMBER GENERATED as IDENTITY

H2의 경우 :

ID BIGINT GENERATED as auto_increment

또한 확인하십시오 :

@Column(insertable = false)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.