Tag Archives: Hibernate

Error : SpringBoot Hibernate 버전충돌

SpringBoot 1.5.7에서 Hibernate 5.0.12 버전을 쓰는데

나는 Hibernate 버전 5.2.11을 사용

SpringBoot플러그인이 의존성을 지맘대로 들고와서 충돌을 일으킨다.

SpringBoot의 ext를 오버라이딩 해 줘야한다.

 

난 버전표시를 이렇게 쓰고 있는데

hibernate_version=5.2.11

스프링부트는 이렇게 쓰고 있다.

이걸 오버라이딩해야되니 한개 더 써준다.

hibernate.version=5.2.11

 

CQRS와 EventSourcing 기술을 보고

CQRS와 EventSourcing제대로 이해를 했나 모르겠는데

비슷한 생각을 하고 그런 설계를 잡으려고 했었는데,
당시에는 Hibernate ORM Envers라는게 있는줄 몰라서…
그 때의 설계는
ORM을 이용한 도메인 설계를 그대로 화면에 보여줄 수 있도록 하고 히스토리는 별도로 저장하는 구조였다.

)를 들어 회원정보 엔티티에서
level 변동, password 변경 등에 대한 히스토리 저장이 필요하다.

RDBMS에서는 다음 엔티티의 현재상태만 저장

UserEntity {
username : string
password : string
passwordChangeDate : date
email : ref EmailEntity
level : type { bronze, silver, gold, platinum, diamond, challenger }
lastLoginDate : date
}

로그는 별도 디비 또는 파일로 관리.
user-password-change-history (password, passwordChangeDate)
user-level-change-history
user-lastLoginDate-history

이런방식으로 현재상태와 변경상태를 저장한다.
변경히스토리를 저장하는 부분을 하나하나코딩하면 안되고,
하이버네이트 인터셉터라던가 해서 데이터변경을 확인하고 로그를 남기도록 하는 추가기능이 필요하다.

이렇게 하는 경우 RDBMS의 데이터가 메인이기 때문에 변경기록이 남지 않게 되는 상황이 생길수도 있다. 중요한 데이터는 트랜잭션을 걸면 느려
계좌 밸런스를 저장하는걸 예로들걸 그랬나

지금 CQRS컨셉으로 제시하는 것을 보면 현재상태는 메모리디비같은데 저장하는 것 같은데 소규모시스템에서 생각 해 보면
RDBMS에 현재상태를 몽땅저장하는게 괜찮아보인다.

이정도로 중규모까지는 사용가능 해 보인다.

RDBMS의 업데이트를 과도하게 사용하는 부분이 문제가 되긴 할텐데…

어쨌든.. envers쓰면 쉽게 된다.
http://hibernate.org/orm/envers/
….
잘도 만들어 놨다. 이걸 왜 못찾았을까 좀만 더 찾아볼걸

Jpa의 @ManyToMany 조인에서 구조상의 문제점

이런 구조의 Account 엔티티가 있다면

위의 groups에 3개 authorities에 2개의 데이터가 있다면 총 6개의 로우가 생성되서 출력이 되는 문제가 발생한다.
이것은 Hibernate에서 자동생성되는 다음과 같은 형태의 쿼리때문에 발생하는데
EAGER인 경우 쿼리를 묶어서 한번에 출력하려고 1개의 쿼리를 만들어내고

이것을 해결하려면

1 Set을 사용해서 중복이 제거되도록 하거나
이 경우 쿼리에서 데이터가 6개가 출력이 될 수도 있지만 중복을 자동으로 제거하게 된다. 이렇게 처리할 경우에는 ManyToMany 조인테이블에서 unique_index가 없어서 중복으로 들어가는게 가능한데 이렇게 데이터가 진짜로 중복으로 들어있는 경우가 발생하는것과 구분이 불가능하다.
2 ManyToMany가 두개이상 사용되는 경우 EAGER를 뺀다.
EAGER를 빼면 getGroups(), getAuthorities()가 실행될 때 별도의 쿼리를 실행시켜서 데이터 중복문제가 해결된다.

 

 

ORM(JPA,Hibernate)의 미세 권한 제어 2

미세권한 제어를 위해 필요했던 기능… 필요로 하던 .. interceptor가 지원이 된다

우선 hibernate 도큐먼트들 링크
https://docs.jboss.org/hibernate/orm/5.0/

인터셉터 관련 자원
https://docs.jboss.org/hibernate/orm/5.0/manual/en-US/html/ch14.html

JACC provider라는게 나오는데 이건 뭘까
보니
엔티티의 crud 권한을 제어하는 것 같다
각로우별 권한제어가 필요한 상황이니 이걸로는 조금 부족한 것 같다
별도처리해야할듯

ORM(JPA,Hibernate)의 미세 권한 제어 1

라고 하면 뭔지 알아듣기 힘들겠지?

일반적으로 spring security와 같은 권한프레임워크의 권한관리는 주소패턴을 따른다.
조금 변경한다고 해도 컨트롤러 서비스별로 권한을 처리한다.

하지만 가끔.. 특정 데이터에 대해서는 이런게 필요한 경우가 있다.
각 테이블별 권한제어
또는 각 테이블의 row당 접근권한 제어..

ORM interceptor를 이용해서 이 부분을 처리할 수 있지 않을까 싶다.

현재 이정도 코드로 하면 되지 않을까 생각하고 있다.
다른 한개의 테이블에 권한을 설정해놓고 다른 테이블의 데이터에 대한 권한을 관리할 수 있다.

데이터가 늘어남에 따라 이 테이블도 비대해지는 문제가 있기는 한데… 문제가 생기면 다시 생각해봐야겠다.

Hibernate 복합키 사용하기

pk여러개 달아놓고 쓰는 방법

pk 순서를 정하는건 잘 안된다.

이 부분을 수정하려면 하이버네이트 코드 커스터마이징을 하던가 해야할듯하다.

위 코드로 생성을 하면 아래의 쿼리가 나온다.

pk순서가 time, code, name이면 좋겠는데… 이 부분이 조절이 잘 안된다. abc순서로 순서가 잡히는거라면 이름을 바꿔서 짓는것도 고려해봐야겠다.

특별히 제공하는 방법은 없는 것 같으니… 하이버네이트에서 어노테이션을 스캔하는 코드를 찾아서 상속받아서 수정하고 다시 쑤셔넣어주는게 좋을듯하다.

소스코드를 찾아서 재컴파일해서 lib폴더나 개인용 mavenrepo에 넣는것보다는… 낫지않을까 하는 생각이다.

Hibernate nativesql 사용시 발생하는 문제

Exception String : org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias [coalesce] during auto-discovery of a native-sql query

환경 : Postgresql, Hibernate 4.x, Java7, Spring3.1 … etc

상황 : 복잡한 조인을 사용해서 DB의 데이터를 조회해야하는 상황..HQL은 익숙하지 않고 Criteria로 하기에는 불편한 상황이라서 native sql을 사용하려고 했는데….

pgadmin에서 돌렸을 때 아무 문제도 없는 상황인데 session.createSQLQuery(queryString)을 사용하면 문제가 발생했다.

 

처리 :

alias문제… coalesce 함수를 두번 사용했는데 두개가 동일한 alias name으로 인식된 것 같다. pagadmin에서는 문제가 없었다.  as iteam1, as item2와 같이 두개에 다른 이름을 부여하니 문제없이 정상 동작했다.

 

 

Hibernate 구현상의 문제점 정리

1. 설계상의 문제

Object구조를 갖추기 위해서인지는 모르겠지만.. Long id를 거의 강제하는 (커스터마이징이 가능하지만 조금 불편…) 도메인 구조때문에 설계에 제약이 생기고 디비의 성능을 제대로 발휘하지 못한다.

 

2. Bulk Insert 동작시

postgresql의 경우 sequence를 가져오기 위해 select nextval(‘{sequencename}’)를 연속으로 호출한다. oracle에서도 마찬가지가 아닐까 싶다. transaction처리를 위해서인것같지만… 문제가 있어보인다. 왜 이렇게 구현되어있는지 찾아봐야할 것 같다.

 

3. SaveOrUpdate 구현상의 문제점

Save And Update 형태로 동작한다.

upsert 기능을 지원하는 디비에서 굳이 저런식으로 동작하는 것은 비효율적이다.

 

하이버네이트에 생겨야 하는 기능들

1. Comment

디비에 커맨트가 안 달아진다. 불편하게…

2. GlobalColumn
공통 컬럼

player은 user와 fk로 묶어놓기 때문에 별도로 username 을 저장하지 않는다.

log데이터는 fk로 묶지 않는 경우가 많기 때문에 userid를 저장하기보다는 username을 저장하는게 좋다. 이런경우…. username은 모두 동일한 구조를 갖는게 좋은데… 코딩하다보면 위처럼.. 섞인다.

이럴경우 공통값을 클래스로 선언해서 미리 등록해놓고 사용하면 이런 문제를 해결할 수 있다.

 

 

언제 시간나면 추가해봐야겠다.

현재 없는 기능이니 삽질하지맙시다.

 

스프링Spring – 하이버네이트Hibernate 연동 개발시에 설정 주의점

1. 테스트용으로 sql파일을 import하는 경우

hibernate.hbm2ddl.import_file = “META-INF/sql/user.sql,META-INF/sql/auth.sql”
이렇게 파일명을 정확히 적어줘야 한다.

“classpath:/META-INF/sql/user.sql”처럼 classpath라고 적으면 오류가 발생한다.
*.sql처럼 regex도 인식하지 못한다.

 

2. Annotation을 이용한 Sequence 생성시

GenerationType.AUTO로 해야 mysql에서  auto_increament가 적용된다. Generation.SEQUENCE라고 하면 SEQUENCE기능이 없는 mysql에서는 오류가 발생한다.

DB에 시퀀스가 생성이 되도 postgresql에서 insert쿼리를 사용시 자동으로 시퀀스가 default로 insert되지 않는다.

insert시에 nextval(‘user_id_seq’)를 명시해줘야하는 불편함이 있다. 오라클은 테스트를 안해봤지만 마찬가지일거라 생각되니 고민하지말고 바로 노가다를 시작…