Hibernate, @SequenceGenerator 및 assignmentSize
우리는 모두 Hibernate를 사용할 때의 기본 동작을 알고 있습니다. @SequenceGenerator
실제 데이터베이스 시퀀스를 1 씩 증가시키고이 값을 50 (기본값 allocationSize
) 으로 곱한 다음이 값을 엔티티 ID로 사용합니다.
이것은 잘못된 동작이며 다음과 같은 사양 과 충돌합니다 .
assignmentSize-(선택 사항) 시퀀스에서 시퀀스 번호를 할당 할 때 증가 할 양입니다.
명확하게 말하면 생성 된 ID 간의 간격에 대해서는 신경 쓰지 않습니다.
기본 데이터베이스 시퀀스와 일치하지 않는 ID에 관심이 있습니다 . 예를 들어 : 다른 애플리케이션 (예 : 일반 JDBC 사용)은 시퀀스에서 얻은 ID 아래에 새 행을 삽입하려고 할 수 있습니다. 그러나 모든 값은 이미 Hibernate에서 사용하고있을 수 있습니다! 광기.
누군가이 문제에 대한 해결책을 알고 allocationSize=1
있습니까 (설정하지 않고 성능 저하)?
편집 :
일을 명확하게하기 위해. 마지막으로 삽입 된 레코드의 ID = 1
이면 HB 51, 52, 53...
는 새 엔티티에 대한 값 을 사용 하지만 동시에 데이터베이스의 시퀀스 값은로 설정됩니다 2
. 다른 응용 프로그램에서 해당 시퀀스를 사용할 때 쉽게 오류가 발생할 수 있습니다.
반면에 : 사양은 (내 이해에서) 데이터베이스 시퀀스가 설정 51
되어야하며 그 동안 HB는 범위의 값을 사용해야 한다고 말합니다.2, 3 ... 50
업데이트 :
Steve Ebersole이 아래에 언급했듯이 : 나에 의해 설명 된 동작 (그리고 많은 사람들에게 가장 직관적 인 동작)은 hibernate.id.new_generator_mappings=true
.
감사합니다.
업데이트 2 :
미래의 독자를 위해 아래에서 작동하는 예를 찾을 수 있습니다.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
@SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS")
private Long id;
}
persistence.xml
<persistence-unit name="testPU">
<properties>
<property name="hibernate.id.new_generator_mappings" value="true" />
</properties>
</persistence-unit>
명확하게 말하면 ... 설명하는 내용이 어떤 식 으로든 사양과 충돌 하지 않습니다 . 스펙은 데이터베이스 시퀀스에 실제로 저장된 값이 아니라 Hibernate가 엔티티에 할당하는 값에 대해 이야기합니다.
그러나 원하는 동작을 얻을 수있는 옵션이 있습니다. 먼저 JPA 주석과 Hibernate를 사용하여 @GeneratedValue 전략을 동적으로 선택하는 방법이 있습니까? 그것은 당신에게 기본을 줄 것입니다. 해당 SequenceStyleGenerator를 사용하도록 설정되어있는 한 Hibernate는 SequenceStyleGenerator allocationSize
에서 "풀링 된 최적화 프로그램"을 사용하여 해석 합니다. "풀링 된 옵티 마이저"는 시퀀스 생성시 "증가"옵션을 허용하는 데이터베이스와 함께 사용하기위한 것입니다 (시퀀스를 지원하는 모든 데이터베이스가 증분을 지원하는 것은 아닙니다). 어쨌든, 거기에서 다양한 최적화 전략에 대해 읽어보십시오.
allocationSize=1
Hibernate는 할당 크기 범위의 값을 할당하려고 시도하기 때문에 쿼리를 얻기 전에 마이크로 최적화이므로 시퀀스에 대한 데이터베이스 쿼리를 피하십시오. 그러나이 쿼리는 1로 설정하면 매번 실행됩니다. 다른 응용 프로그램에서 데이터베이스에 액세스하면 그 동안 다른 응용 프로그램에서 동일한 ID를 사용하면 문제가 발생하기 때문에 거의 차이가 없습니다.
차세대 시퀀스 ID는 assignmentSize를 기반으로합니다.
기본적으로 그것은 50
너무 많은 것으로 유지됩니다 . 또한 50
한 세션에서 거의 유지되지 않고이 특정 세션 및 트랜잭션을 사용하여 유지 될 레코드에 대해 거의 도움 이 될 것입니다.
따라서을 사용 allocationSize=1
하는 동안 항상 사용해야 SequenceGenerator
합니다. 대부분의 기본 데이터베이스 시퀀스는 항상 1
.
스티브 에버 솔과 다른 멤버들,
갭이 더 큰 (기본값은 50) 아이디에 대한 이유를 친절하게 설명해 주시겠습니까? Hibernate 4.2.15를 사용하고 있으며 org.hibernate.id.enhanced.OptimizerFactory cass에서 다음 코드를 발견했습니다.
if ( lo > maxLo ) {
lastSourceValue = callback.getNextValue();
lo = lastSourceValue.eq( 0 ) ? 1 : 0;
hi = lastSourceValue.copy().multiplyBy( maxLo+1 );
}
value = hi.copy().add( lo++ );
if 문 내부에 도달 할 때마다 hi 값이 훨씬 커집니다. 따라서 빈번한 서버 재시작으로 테스트하는 동안 내 ID는
1, 2, 3, 4, 19, 250, 251, 252, 400, 550, 750, 751, 752, 850, 1100, 1150 과 같은 시퀀스 ID를 생성합니다 .
이미 사양과 충돌하지 않는다고 말씀 하셨지만 대부분의 개발자에게는 예상치 못한 상황이 될 것이라고 생각합니다.
모든 사람의 의견이 많은 도움이 될 것입니다.
Jihwan
UPDATE: ne1410s: Thanks for the edit.
cfrick: OK. I will do that. It was my first post here and wasn't sure how to use it.
Now, I understood better why maxLo was used for two purposes: Since the hibernate calls the DB sequence once, keep increase the id in Java level, and saves it to the DB, the Java level id value should consider how much was changed without calling the DB sequence when it calls the sequence next time.
For example, sequence id was 1 at a point and hibernate entered 5, 6, 7, 8, 9 (with allocationSize = 5). Next time, when we get the next sequence number, DB returns 2, but hibernate needs to use 10, 11, 12... So, that is why "hi = lastSourceValue.copy().multiplyBy( maxLo+1 )" is used to get a next id 10 from the 2 returned from the DB sequence. It seems only bothering thing was during the frequent server restart and this was my issue with the larger gap.
So, when we use the SEQUENCE ID, the inserted id in the table will not match with the SEQUENCE number in DB.
After digging into hibernate source code and Below configuration goes to Oracle db for the next value after 50 inserts. So make your INST_PK_SEQ increment 50 each time it is called.
Hibernate 5 is used for below strategy
Check also below http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators-sequence
@Id
@Column(name = "ID")
@GenericGenerator(name = "INST_PK_SEQ",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
@org.hibernate.annotations.Parameter(
name = "optimizer", value = "pooled-lo"),
@org.hibernate.annotations.Parameter(
name = "initial_value", value = "1"),
@org.hibernate.annotations.Parameter(
name = "increment_size", value = "50"),
@org.hibernate.annotations.Parameter(
name = SequenceStyleGenerator.SEQUENCE_PARAM, value = "INST_PK_SEQ"),
}
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INST_PK_SEQ")
private Long id;
I would check the DDL for the sequence in the schema. JPA Implementation is responsible only creation of the sequence with the correct allocation size. Therefore, if the allocation size is 50 then your sequence must have the increment of 50 in its DDL.
This case may typically occur with the creation of a sequence with allocation size 1 then later configured to allocation size 50 (or default) but the sequence DDL is not updated.
I too faced this issue in Hibernate 5:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE)
private Long titId;
Got a warning like this below:
Found use of deprecated [org.hibernate.id.SequenceHiLoGenerator] sequence-based id generator; use org.hibernate.id.enhanced.SequenceStyleGenerator instead. See Hibernate Domain Model Mapping Guide for details.
Then changed my code to SequenceStyleGenerator:
@Id
@GenericGenerator(name="cmrSeq", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
@Parameter(name = "sequence_name", value = "SEQUENCE")}
)
@GeneratedValue(generator = "sequence_name")
private Long titId;
This solved my two issues:
- The deprecated warning is fixed
- Now the id is generated as per the oracle sequence.
참고URL : https://stackoverflow.com/questions/12745751/hibernate-sequencegenerator-and-allocationsize
'programing tip' 카테고리의 다른 글
Android에 새 네트워크 베어러 추가 (0) | 2020.08.14 |
---|---|
TPM (Trusted Platform Module)을 사용하여 바이트를 암호화하는 방법 (0) | 2020.08.14 |
요구 사항을 충족하는 버전을 찾을 수 없습니다. (0) | 2020.08.14 |
Firefox 4의 text-overflow : ellipsis? (0) | 2020.08.14 |
어떤 프로세스가 글로벌 핫키를 등록했는지 알아보세요? (0) | 2020.08.14 |