Tag Archives: JPA

Java -> Kotlin 전환시 발생하는 문제들 + 안좋은점

JPA모델설계시

Java에서는 @OneToOne Many등 표시안하고 그냥써도 됐는데.. Kotlin에서는 오류가 난다.

kotlin data class constructor

생성자 만드는게 몹시 짜증이난다다
써보니 이름이 왜 꼬출린인지 알겠다

자동완성이 구리다

자바개발에서 귀찮은 getter, setter, slf4j은 lombok으로 처리해서 귀찮은 자바의 단점이었던 난잡한 코드 문제가 많이 해결됐는데

변수 선언에서 자동완성이 좀 안된다.

 

java는 클래스명을 쓰면 변수명이 자동으로 나올 수 있는데
Kotlin은 … 그게안된다.

커뮤니티에 엉터리가 많다

아직 초보자들이 많은지 잘못된 정보가 간혹 있다.
JPA Entity설계할 때 dataclass를 사용하라고 한다던가 하는…
해보니까 그냥 class로 선언하는게 편하다.
아닌가?? 더 익숙해지면 data class가 더 나을까?

QueryDSL 미지원

QueryDSL에서는 Gradle을 공식적으로 지원하지 않는건가?
github에 가보니 maven만 있고 Gradle은 안 보인다.
third party를 이용해서 하긴했는데…
Kotlin은 변환이 안된다. (이것은 아직 지원안되는 것 같다)
결국 Entity는 Java로 다시 변환했다.

Java와 혼용시 문제

Java와 Kotlin을 같은 프로젝트에 섞어서 쓰면 kotlin에서 lombok의 getter, setter이 인식되지 않는다. (컴파일 타임의 문제니까 노력하지말자 – lombokforkotlin을 만들게 아니라면)
멀티모듈로 하면 상위 코드의 core를 조회 가능
groovy가 더 잘 섞이는 것 같다. 테스트코드 짤 때 써볼라고하니까

결론

꽤 안정화됐지만 그래도 아직 갈길이 멀었다.
아직 한창 개발중인 언어로, 언어 자체의 문제로 인한 버그가 간혹 존재한다.
그리고 현재의 문법체계가 언제까지 유지될거라고 보기도 힘들다.
IDE, 프레임워크, 라이브러리 지원도 아직은 Java를 대체할 수준은 아니다.

가장 오류없이 무난한 개발을 하려면 Maven-Java

좀 고생을 하더라도 다른거 써보고 싶으면 다른거 쓰면 될 것 같다.

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

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

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

이것을 해결하려면

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

 

 

Spring Data JpaRepository 사용시 주의점. 이름중복. no such method

요즘 잘 기록을 안해놓다보니…

에러로그를 잃어버렸다.

이런 종류의 오류가 발생하는 경우에는 실행 순서에 따라 되다말다 하는 경우가 많아서 원인 찾기가 힘든데

사실 이것도 정확히 해결이라기보다는 원인 비슷한 것을 찾은 상황… 맞음말고 아님또말고다.

오류상황

PageEntity, 그리고 PageRepository extends JpaRepository<PageEntity, Long>

형태로 사용했는데

테스트코드에서는 이상없이 동작하지만… 웹에서 호출을 하면 오류가 발생하는 상황

해결

혹시나 해서…

PageEntityRepository로 변경을 했다.

무슨 에러로그를 보고 이걸 떠올렸었는데…

 

그러니까

네이밍을 중복 안되게 잘하쟈는…

스프링같은 라이브러리에서 네이밍을 할 때 프리픽스를 좀 붙여주면 좋겠다.

SPPageEntity 라던가.. 애플은 NSString이렇게 하는것처럼..

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

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

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

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

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

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

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

Hibernate Jpa Criteria쿼리

도메인 구조

도메인 구조는 동일하다. 하이버네이트 전용 어노테이션이나 스프링Data전용 어노테이션 등등이 있긴한데…
여기저기서 JPA걸쓰면 다 먹히니까 특별한 용도가 아니면 JPA어노테이션을 사용하는게 좋다.

Jpa 쿼리

JPA는 이런느낌.. 뭐 다를게 없는데 구조가 살짝 다르다.

하이버네이트

no transaction is in progress – jpa셋팅중에 만난 알수없는 메세지.

javax.persistence.TransactionRequiredException: no transaction is in progress

웹셋팅을 마치고 나니 이런 메세지가 뜨면서 addPost가 동작하지 않는다.

그래서 junit을 통해 테스트코드를 만드니까 돌아간다.

여기서 @transactional태그와 관련된 문제라는 판단.

한마디로 Junit에서는 @Transactional태그가 먹히고 Web에서는 먹히지 않는다.

Jpa의 셋팅이 DiapatcherServlet의 servlet-context에서 재 로딩되면서 발생하는 문제가 아닐까 싶었다.

 

해결방안으로 생각했던 것이… 모든 셋팅을 root로 옮기는것.

그러면 로딩할때 한꺼번에 해서 이런 문제가 안 생기지 않을까 싶었다

근데 귀찮아서 나랑 비슷한 상황이 있나 한번 더 검색해보니…

http://stackoverflow.com/questions/10633240/spring-jpa-transactions-works-only-in-junit-test-but-not-in-application/10869397#10869397

exactly same problem이 나왔다.

servlet에 <tx:annotation-driven/>을 추가해주랜다.

잘된다.

설정 깔끔하게 하려고 필요없는거 이것저것 제외하고 하다보면 이런 문제를 더 많이 겪는 것 같다. 옛날에 잘 할줄모를때는 이것저것 지저분하게 막 갖다껴놔가지고 그냥 대충 막 돌아갔었는데

Hibernate 복합키 사용하기

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

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

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

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

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

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

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

SpringData, JPA, Hibernate 적용하기

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

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

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

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

 

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

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

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

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

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

 

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

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

 

 

 

하이버네이트, JPA 참고 소스, 사이트

http://krams915.blogspot.kr/2011/01/spring-mvc-3-hibernate-annotations.html

git://github.com/michaelisvy/hibernate-4-spring-3.1-samples.git

git://github.com/SpringSource/spring-data-jpa-examples.git https://github.com/SpringSource/spring-data-jpa-examples

custom value type

http://stackoverflow.com/questions/735732/mapping-enum-to-a-table-with-hibernate-annotation

 

http://www.objectdb.com/

 

git://github.com/SpringSource/spring-data-book.git

git://github.com/appoxy/simplejpa.git

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/jpa.repositories.html#jpa.java-config