휴지 상태 JPA 시퀀스(비ID)
식별자가 아니거나 복합 식별자의 일부가 아닌 일부 열에 대해 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());
는 생성되지 않습니다.mySequenceVal
JPA를 사용하다
확실히 하기 위해서입니다.최대 절전 모드로 전환하여mySequencedValue
할 수 있지만 자체 값을 .Hibernate가 데이터베이스 생성 값을 처리할 수 있다는 것은 알지만 트리거나 Hibernate 자체 이외의 다른 것을 사용하여 속성 값을 생성하고 싶지 않습니다.휴지 상태가 기본 키의 값을 생성할 수 있는 경우 단순 속성으로 생성할 수 없는 이유는 무엇입니까?
이 문제에 대한 답을 찾다가 우연히 이 링크를 발견했습니다.
JILLY/JILLY/JILLY-JILLY-JILLY-JILLY-JILLY-JILLY-JILLY-JILLY-JPA는 ID가 아닌 속성에 대한 값을 자동으로 생성할 수 없습니다.@GeneratedValue
은 오직 '주석'과 함께 합니다.@Id
자동 리셋을 만듭니다.
@GeneratedValue
주석은 데이터베이스가 이 값 자체를 생성하고 있음을 Hibernate에 알립니다.
이 포럼에서 제안하는 솔루션(또는 회피책)은 다음과 같은 ID를 가진 개별 엔티티를 작성하는 것입니다.
@엔티티퍼블릭 클래스 General Sequence Number {@Id@GeneratedValue(...))개인 긴 번호} @엔티티퍼블릭 클래스 MyEntity {@Id.. 개인 롱 아이디 @원투원(...))사설 GeneralSequnceNumber myVal;}
.@Column(columnDefinition="serial")
Postgre "에서만 합니다.SQL. 두 번째 엔티티는 "추악한" 옵션이기 때문에 이 솔루션은 저에게 완벽한 솔루션이었습니다.
의 콜saveAndFlush
엔티티도 합니다.save
DB를 사용합니다.
매우 오래된 질문인 것은 알지만, 우선 결과에 나타나 있고, 질문 이후 jpa가 많이 바뀌었습니다.
the the the the the the the the the the the the the the the the the the the the 를 사용하는 것입니다.@Generated
열을 으로 설정한 과 같이 수 .시퀀스를 정의하고 컬럼의 기본값을 해당 시퀀스로 설정한 후 컬럼을 다음과 같이 매핑할 수 있습니다.
@Generated(GenerationTime.INSERT)
@Column(name = "column_name", insertable = false)
하이버네이트는 확실히 이것을 서포트합니다.문서에서:
"생성된 속성은 데이터베이스에 의해 생성된 값이 있는 속성입니다.일반적으로 휴지 상태 응용 프로그램은 데이터베이스가 값을 생성하는 속성을 포함하는 개체를 새로 고쳐야 합니다.그러나 속성을 생성된 것으로 표시하면 응용 프로그램에서 이 책임을 휴지 상태로 위임할 수 있습니다.기본적으로 Hibernate는 생성된 속성을 정의한 엔티티에 대해 SQL INSERT 또는 UPDATE를 발행할 때마다 즉시 Select를 발행하여 생성된 값을 가져옵니다."
삽입 시에만 생성된 속성의 경우 속성 매핑(.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가 이러한 휴지 상태 기능을 제공하는지는 알 수 없지만, 휴지 상태에서는 이러한 기능을 지원합니다.
Hibernate를 사용하여 UUID(했습니다.@PrePersist
★★★★
@PrePersist
public void initializeUUID() {
if (uuid == null) {
uuid = UUID.randomUUID().toString();
}
}
그 후, 다음과 같이 작업을 실시했습니다.
@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();
}
스레드가 오래된 것 같습니다.솔루션을 여기에 추가하려고 합니다(봄에 AFP를 사용).
것입니다.@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;
}
postgresql을 사용하는
저는 1.5.6에하고 있습니다.
@Column(columnDefinition = "serial")
@Generated(GenerationTime.INSERT)
private Integer orderID;
오래된 스레드이지만 솔루션을 공유하고 피드백을 받고 싶습니다.주의: 이 솔루션은 일부 JUnit 테스트 케이스에서 로컬 데이터베이스로만 테스트한 것입니다.따라서 이 기능은 아직까지는 생산적이지 않습니다.
저는 속성 없는 시퀀스라는 커스텀 주석을 도입하여 이 문제를 해결했습니다.증분 시퀀스에서 값을 할당해야 하는 필드의 마커일 뿐입니다.
@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;
....
}
데이터베이스 독립성을 유지하기 위해 시퀀스 전류 값과 증분 크기를 유지하는 Sequence Number라는 엔티티를 도입했습니다.각 엔티티 클래스가 고유한 시퀀스를 얻을 수 있도록 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;
}
}
}
위의 코드에서 알 수 있듯이 리스너는 엔티티 클래스마다 1개의 Sequence Number 인스턴스를 사용하여 Sequence Number 엔티티의 increment Value에 의해 정의된 시퀀스 번호를 몇 개 예약합니다.시퀀스 번호가 부족하면 타깃클래스의 Sequence Number 엔티티를 로드하고 다음 콜의 increment Value 값을 예약합니다.이렇게 하면 시퀀스 값이 필요할 때마다 데이터베이스를 조회할 필요가 없습니다.다음 시퀀스 번호 세트를 예약하기 위해 열려 있는 Stateless Session에 주의하십시오.현재 대상 엔티티가 유지되고 있는 세션과 동일한 세션을 사용할 수 없습니다. 그러면 동시 수정이 발생합니다.EntityPersister에 예외가 있습니다.
이게 도움이 됐으면 좋겠네요.
저도 당신과 같은 상황에서 달리고 있고, JPA와의 아이디 이외의 속성을 기본적으로 생성할 수 있는지 여부에 대한 진지한 답변을 찾지 못했습니다.
이 솔루션은 네이티브 JPA 쿼리를 사용하여 시퀀스를 호출하여 속성을 수동으로 설정한 후 계속하는 것입니다.
이것은 만족스럽지 않지만 일단은 회피책으로 작용합니다.
마리오
JPA 사양의 세션 9.1.9 GeneratedValue Annotation에서 "[43] 휴대용 응용 프로그램은 다른 영구 필드나 속성에 GeneratedValue 주석을 사용하면 안 됩니다."라는 특정 메모를 발견했습니다.따라서 적어도 JPA만으로 비프라이머리 키 값의 값을 자동 생성하는 것은 불가능하다고 생각합니다.
당신은 당신이 원하는 것을 정확히 할 수 있습니다.
Hibernate의 Identifier Generator 구현을 Integrator에 등록함으로써 적응할 수 있다는 것을 알게 되었습니다.이것에 의해, 휴지 상태로부터 제공된 임의의 id 시퀀스 생성기를 사용해 비id 필드의 시퀀스를 생성할 수 있습니다(순차적이지 않은 id 생성기도 동작할 가능성이 있습니다).
이 방법으로 ID를 생성하는 방법에는 많은 옵션이 있습니다.Identifier Generator, 특히 Sequence Style Generator와 Table Generator의 구현을 확인하십시오.@GenericGenerator 주석을 사용하여 생성기를 구성한 경우 이러한 클래스의 매개 변수를 잘 알고 있을 수 있습니다.또한 Hibernate를 사용하여 SQL을 생성할 수도 있습니다.
작동 방법은 다음과 같습니다.
import org.hibernate.Session;
import org.hibernate.boot.Metadata;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.enhanced.TableGenerator;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.internal.SessionImpl;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.type.LongType;
import java.util.Properties;
public class SequenceIntegrator implements Integrator, ValueGenerator<Long> {
public static final String TABLE_NAME = "SEQUENCE_TABLE";
public static final String VALUE_COLUMN_NAME = "NEXT_VAL";
public static final String SEGMENT_COLUMN_NAME = "SEQUENCE_NAME";
private static SessionFactoryServiceRegistry serviceRegistry;
private static Metadata metadata;
private static IdentifierGenerator defaultGenerator;
@Override
public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactoryImplementor, SessionFactoryServiceRegistry sessionFactoryServiceRegistry) {
//assigning metadata and registry to fields for use in a below example
SequenceIntegrator.metadata = metadata;
SequenceIntegrator.serviceRegistry = sessionFactoryServiceRegistry;
SequenceIntegrator.defaultGenerator = getTableGenerator(metadata, sessionFactoryServiceRegistry, "DEFAULT");
}
private TableGenerator getTableGenerator(Metadata metadata, SessionFactoryServiceRegistry sessionFactoryServiceRegistry, String segmentValue) {
TableGenerator generator = new TableGenerator();
Properties properties = new Properties();
properties.setProperty("table_name", TABLE_NAME);
properties.setProperty("value_column_name", VALUE_COLUMN_NAME);
properties.setProperty("segment_column_name", SEGMENT_COLUMN_NAME);
properties.setProperty("segment_value", segmentValue);
//any type should work if the generator supports it
generator.configure(LongType.INSTANCE, properties, sessionFactoryServiceRegistry);
//this should create the table if ddl auto update is enabled and if this function is called inside of the integrate method
generator.registerExportables(metadata.getDatabase());
return generator;
}
@Override
public Long generateValue(Session session, Object o) {
// registering additional generators with getTableGenerator will work here. inserting new sequences can be done dynamically
// example:
// TableGenerator classSpecificGenerator = getTableGenerator(metadata, serviceRegistry, o.getClass().getName());
// return (Long) classSpecificGenerator.generate((SessionImpl)session, o);
return (Long) defaultGenerator.generate((SessionImpl)session, o);
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactoryImplementor, SessionFactoryServiceRegistry sessionFactoryServiceRegistry) {
}
}
이 클래스는 META-INF/services 디렉토리에 등록해야 합니다.Hibernate 문서에서는 Integrator 등록에 대해 다음과 같이 설명합니다.
휴지 상태 시작 시 인테그레이터를 자동으로 사용하려면 META-INF/services/org.hibernate를 추가해야 합니다.integrator.spi.인테그레이터 파일을 항아리에 넣습니다.파일에는 인터페이스를 구현하는 클래스의 완전 수식 이름이 포함되어 있어야 합니다.
이 클래스는 Value Generator 클래스를 구현하기 때문에 @Generator와 함께 사용할 수 있습니다.주석을 입력하여 순차 값을 자동으로 생성합니다.클래스의 설정 방법은 다음과 같습니다.
@Entity
@Table(name = "MyTable")
public class MyEntity {
//...
@Id //... etc
public Long getId() {
return id;
}
@GeneratorType(type = SequenceIntegrator.class, when = GenerationTime.INSERT)
@Column(name = "SEQ_VAL", unique = false, nullable = false, insertable = true, updatable = true)
public Long getMySequencedValue(){
return myVal;
}
}
@Morten Berg가 인정해 준 솔루션 옆에 다른 솔루션을 제공하고 싶습니다.이 솔루션은 나에게 더 효과적입니다.
하면 실제로 할 수 .Number
- 형 - - -Long
내 사용 예에서는 - 대신GeneralSequenceNumber
이것은, JSON(디시리얼라이제이션)등의 경우에 편리합니다.
단점은 데이터베이스 오버헤드가 조금 더 필요하다는 것입니다.
'아, 아, 아'가 필요해요.ActualEntity
auto-displayed()를 원하는 generated
입입 of Long
:
// ...
@Entity
public class ActualEntity {
@Id
// ...
Long id;
@Column(unique = true, updatable = false, nullable = false)
Long generated;
// ...
}
다음,가 필요합니다.Generated
는 package-private 옆에 ActualEntity
패키지의 구현 세부사항을 유지하려면 다음과 같이 하십시오.
@Entity
class Generated {
@Id
@GeneratedValue(strategy = SEQUENCE, generator = "seq")
@SequenceGenerator(name = "seq", initialValue = 1, allocationSize = 1)
Long id;
}
우리는 '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 네.ActualEntity
a, 은, 델, 의를 생성하여 Generated
그러면 된 데이터베이스 가 제공됩니다.id
타입의Long
이 값은 다음 주소로 작성함으로써 사용합니다.ActualEntity.generated
.
사용 예에서는 Spring Data REST를 사용하여 구현했습니다.@RepositoryEventHandler
이 명령어는 다음 명령어를 사용하기 직전에 호출됩니다.ActualEntity
질기게게하하하하다
@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);
}
}
실제 어플리케이션에서는 테스트하지 않았으니 주의해서 즐겨주세요.
"트리거나 휴지 상태 이외의 다른 것을 사용하여 속성 값을 생성하지 않습니다."
이 경우 필요한 값을 생성하는 UserType 구현을 만들고 mySequenceVal 속성의 지속성을 위해 UserType을 사용하도록 메타데이터를 구성하는 것은 어떻습니까?
이것은 시퀀스를 사용하는 것과는 다릅니다.시퀀스를 사용할 때 아무것도 삽입하거나 업데이트하지 않습니다.단순히 다음 시퀀스 값을 가져옵니다.휴지 상태에서는 지원되지 않는 것 같습니다.
삽입 시 UNIQUIRE IDENTIFIER 유형 및 기본 생성이 필요한 열이 있지만 열이 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"
컬럼타입에서도 됩니다). 다른 열 유형에서도 동일하게 시도합니다.
Spring 어플리케이션에서 @PostConstruct 및 JdbcTemplate를 사용하여 MySql 데이터베이스에서 이 문제를 해결할 수 있는 방법을 찾았습니다.다른 데이터베이스에서도 가능하지만 MySql에서 auto_increment를 사용하기 때문에 제가 소개할 사용 사례는 저의 경험을 바탕으로 합니다.
먼저 @Column 주석의 ColumnDefinition 속성을 사용하여 auto_increment로 열을 정의하려고 했지만, 열이 자동으로 증분하기 위해 키가 될 필요는 없었지만, 열이 정의된 후에야 인덱스로 정의되어 교착 상태가 발생하였습니다.
여기서 auto_increment 정의 없이 컬럼을 만들고 데이터베이스 작성 후 컬럼을 추가하는 아이디어를 얻었습니다.이것은 JdbcTemplate의 업데이트 메서드와 함께 응용 프로그램이 콩을 초기화한 직후 메서드를 호출하는 @PostConstructure 주석을 사용하여 가능합니다.
코드는 다음과 같습니다.
내 엔티티:
@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;
//...
}
PostConstruct Component 클래스의 경우:
@Component
public class PostConstructComponent {
@Autowired
private JdbcTemplate jdbcTemplate;
@PostConstruct
public void makeMyEntityMySequencedValueAutoIncremental() {
jdbcTemplate.update("alter table MyTable modify mySequencedValue int unsigned auto_increment");
}
}
나는 오늘 이것 때문에 고생했는데, 이것을 이용해서 해결할 수 있었다.
@Generated(GenerationTime.INSERT)
@Column(name = "internal_id", columnDefinition = "serial", updatable = false)
private int internalId;
저도 당신과 같은 상황(@Id 이외의 필드에서는 JPA/Hibernate 시퀀스)을 겪었는데, 결국 삽입 시 고유한 시퀀스 번호를 추가하는 트리거를 db 스키마에 작성하게 되었습니다.JPA/Hibernate에서는 사용할 수 없었습니다.
몇 시간 동안 시간을 보낸 후, 이것은 문제를 해결하는 데 깔끔하게 도움이 되었습니다.
Oracle 12c의 경우:
ID NUMBER GENERATED as IDENTITY
H2의 경우:
ID BIGINT GENERATED as auto_increment
또, 다음과 같이 합니다.
@Column(insertable = false)
언급URL : https://stackoverflow.com/questions/277630/hibernate-jpa-sequence-non-id
'source' 카테고리의 다른 글
렌더링 후 코드 반응 (0) | 2022.09.18 |
---|---|
python MySQLDB IN 절에서 사용할 목록 삽입 (0) | 2022.09.18 |
한 리터럴 값으로 동일한(=)과 IN 사이의 성능 차이 (0) | 2022.09.18 |
window.close 및 self.close는 Chrome에서 창을 닫지 않습니다. (0) | 2022.09.18 |
JavaScript 개체를 빠르게 지우려면 어떻게 해야 합니까? (0) | 2022.09.18 |