시퀀스에서 ID를 생성하기 위한 Oracle Trigger의 하이버넌트 문제
시퀀스에서 다음 값을 얻는 삽입 전 트리거가 있습니다.개체가 save() 메서드로 지속되면 hibernate는 시퀀스에서 값을 가져와 개체에 추가합니다.그리고 Spring의 서비스 계층에서 트랜잭션이 커밋되면 데이터베이스에서 ID 값이 다시 증가합니다.개체에 ID가 이미 있는 경우 nextval()을(를) 가져오지 않으려면 어떻게 해야 합니까?
여기 제가 하려는 일이 있습니다.
UserDao
public User saveUser(User user){
session.getCurrentSession.save(user);//line2
return user;//line3
}
사용자 서비스
public void saveUserAndWriteToAudit(User user, UserAudit userAudit){
userDao.saveUser(user);//line1
userAudit.setUserId(user.getId);//line4
userAudit.saveUserAudit(userAudit);//line5
}
그리고 사용자 클래스
@Entity
public class User{
@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="a1")
@SequenceGenerator(name="a1", sequenceName="usersequence")
private Long id;
/////////////////
}
커서가 line1에 도달하면 line2 사용자 객체는 null in id 속성을 갖습니다. line2 뒤에는 nextval from sequence를 갖습니다. line4에서는 useraudit object에 사용자의 id=1을 추가했습니다.5행 뒤에 트랜잭션이 커밋되면 2는 User's id 열에, 1은 UserAudit's userId 열에 삽입됩니다.이는 제게 아무런 도움이 되지 않습니다. ( 이 문제를 방지하려면 어떻게 해야 합니까?감사합니다!
ID가 주어지지 않았을 때만 발사되도록 트리거를 업데이트하면 됩니다.
create or replace
trigger sa.my_trigger
before insert on sa.my_table
for each row
when (new.id is null)
begin
select sa.my_sequence.nextval
into :new.id
from dual;
end;
위의 해결책은 훌륭해요, 이 문제에 대한 많은 고민을 덜어줬어요.
제 유일한 불만은 시퀀스를 실제로 조회하지 않고 사용자/코드에 대한 문을 열어 ID 값을 삽입한다는 것입니다.
다음과 같은 해결책도 효과가 있다는 것을 알았습니다.Hibernate가 최대 ID를 찾고 삽입문이 실행될 때마다 증가하도록 합니다.그러나 데이터베이스에 도달하면 ID가 무시되고 트리거에 의해 생성된 ID로 대체되므로 클러스터 문제에는 고유성이 없습니다.
@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
private Long id;
가장 큰 단점은 @GenericGenerator가 Hibernate 주석이므로 JPA의 휴대성을 잃게 된다는 것입니다.또한 이 ID가 실제로 시퀀스에 연결되어 있는지는 프로그래머에게 명확하지 않지만 실제로 시퀀스를 사용하는 가장 엄격한 결합 솔루션 중 하나입니다.
BEFORE INSERT 트리거를 제거하는 것이 이상적입니다.그렇지 않다면, 하이버네이트는 기본 키를 알 방법이 없고, 그 정보가 정말로 필요합니다.INSERT 후에 개체를 신경쓰지 않는다면 괜찮을 수도 있지만(2단계 캐시는 여전히 문제가 있음), 당장 사용해야 한다면 정말 문제입니다.후자의 경우에는 다음과 같은 고약한 접근법을 시도해 볼 수 있습니다.
- Hibernate에게 기본 키를 직접 관리한다고 말합니다.
- 새 개체를 만들고 임의의 값을 기본 키에 넣습니다.
- 최대 절전 모드 세션을 플러시하고 시퀀스를 선택합니다.CURVAL (INSERT가 하나만 있다고 가정).
- 획득한 현재 시퀀스 값을 사용하여 개체를 로드하고 위의 인스턴스를 사용하지 않습니다.
create or replace
trigger sa.my_trigger
before insert on sa.my_table
for each row
when (new.id is null)
begin
select sa.my_sequence.nextval
into :new.id
from dual;
end;
이것은 데이터베이스 세계에서 정말 잘못된 것입니다.
위의 솔루션을 고려하면 sa.my _sequence.nextval을 51이라고 하면 최대 절전 모드 프레임워크는 문제없이 작동합니다.그러나 만약 누군가가 당신의 주요 키 값을 66으로 하는 직접 jdbc 삽입을 시퀀스를 재정의하는 것으로 만든다면(예를 들어, 현재 값을 52로 하는 것), 트리거는 그냥 삽입될 것입니다.
실제 문제는 시퀀스 값이 66으로 증가하면 시퀀스 값을 재설정하는 트리거 엔딩에서 예외가 발생한다는 것입니다.이것은 정말로 데이터베이스 측면에서 볼 때 스키마 설계의 잘못된 구조로 끝납니다.
언급URL : https://stackoverflow.com/questions/8002119/hibernate-issue-with-oracle-trigger-for-generating-id-from-a-sequence
'programing' 카테고리의 다른 글
마리아에서 SELECT IF 내부에 INSERT를 실행할 수 있습니까?DB (0) | 2023.09.14 |
---|---|
SQL Server에서 수백만 행의 큰 테이블을 업데이트하는 방법은 무엇입니까? (0) | 2023.09.14 |
Wordpress 블로그의 RSS 피드에서 MathJax 사용 (0) | 2023.09.14 |
Excel의 열 너비를 R로 정의 (0) | 2023.09.14 |
팬더 데이터 프레임에서 두 열의 값을 단일 열로 병합합니다. (0) | 2023.09.14 |