Tag Archives: Hibernate

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’)를 명시해줘야하는 불편함이 있다. 오라클은 테스트를 안해봤지만 마찬가지일거라 생각되니 고민하지말고 바로 노가다를 시작…

 

Hibernate 쿼리 날리기 – hql, criteria

Criteria 쿼리

 

HQL 쿼리

Users 테이블이 있는 경우

Select * from Users;

from com.beansugar.templates.dto.Users 와 같은 형태의 쿼리

 

SpringData, JPA, Hibernate 적용하기

그냥 프로젝트를 사용하는 경우에는 아주 쉽게 적용이 가능하다.

템플릿에 있는대로 설정하면 된다.

hibernate.cfg.xml을 classpath;~ 경로에 놓고 셋팅해준다.

—-설정방법은 검색, 또는 이클립스 기능을 따라가면서 완성 —-

 

MVC의 경우에는 스프링에서 관리하는 빈 형태를 유지해줘야하는데 이 때문에 설정이 더욱 복잡해진다.

임의로 Bean형태를 삽입하고튜토리얼에 있는 생성코드를 삽입해주면 간단하다.

윗쪽은 SessionFactory생성코드 아랫쪽은 entityManagerFactory생성코드… bean에 이 코드를 대충 쑤셔넣고 임의로 생성된 그 bean을 받아서 사용할 수도 있을 것 같다.
스프링에 연결하는 코드도 대략 그 형태일 것이라 짐작된다.

개발자라면…. 이런 조잡한 방법보다 조금 더 깔끔한 방법을 원한다.

위 방법을 사용하면 dao 코드도 만들어서 콜백을 쑤셔넣고 해야되는 귀찮음이 있다.

 

SpringFramework + SpringData(JPA프레임워크) + Hibernate

이렇게 하면 귀찮은 dao코드를 제거한 채로 코딩이 가능하다고 한다.