'Hibernate'에 해당되는 글 2건

  1. 2009.09.14 Implementing composite keys with JPA and Hibernate (3)
  2. 2008.08.22 골치 아픈 문제 해결 _ Spring, Hibernaate
2009.09.14 09:00

Implementing composite keys with JPA and Hibernate

The issue of the legacy database schema

Stephen B. Morris (stephenbjm@yahoo.com), CTO, Omey Communications

Summary:  Nowadays, with the widespread use and deployment of Object-Relational Mapping (ORM) tools, you don't generally have to think too hard about such arcane issues as composite keys. Normally, the choice of key design can be a simple integer, and this can be left with confidence to the tooling. Occasionally, you come across a situation where a composite key is required, and you need a strategy for this. This tip shows you how to implement composite keys with JPA and Hibernate.

URL : http://www.ibm.com/developerworks/java/library/os-hibernatejpa/index.html?ca=dgr-jw22JPA-Hibernate&S_TACT=105AGX59&S_CMP=grjw22

신고
Trackback 0 Comment 3
2008.08.22 13:21

골치 아픈 문제 해결 _ Spring, Hibernaate

진행중인 프로젝트에서, 어제 문제가 약간 발생했었다.
두 개의 테이블이 있는데, Child table에는 parent에 종속된 개수 만큼 로우가 저장된다.
Cabinet이라는 테이블과 Door라는 테이블이 1 - N으로 되어 있다. Door에는 Cabinet에서 설정된 문 개수만큼 로우가 들어가게 된다. 그리고 편하게 처리하기 위해서 Cabinet에도 Door_Count라는 컬럼을 가지고 있다. 명백하게 말하면 정규화 제 2법칙인가를 위반하고 있다. 종속성이 있으니깐(이게 맞나 ㅎㅎ)
그래도 손쉽게 쿼리를 만들기 위해서 이렇게 처리 했다. 그런데 Door는 개수가 변경 되더래도, 줄어든다면 이전의 Door 번호는 Deleted 라고 컬럼이 설정 되고 실제로 지워지지는 않는다. 그리고 초기 등록 시 문 개수가 4개라도 6개의 데이터가 들어가서 1 ~ 4번은 valid 하고 5, 6번 문은 상태를 delete로 변경해 둔다.
이 때 Cabinet을 중심으로 Door까지 join select하면 Hibernate Filter 기능으로 Door가 delete되면 select 하지 않는다.
문제는 여기에서 발생했다. 이전에 Door가 4개 였다. 다시 6으로 바꾸려면, Door Object의 delete 속성을 false로 바꿔야 하는데, 이 때 실제로 fetch 된 Door는 delete가 false인 것들 즉 4개만 select 되어 버린다. 따라서 update가 제대로 이루어 지더래도, Cabinet의 door count는 6이지만 실제로 Door의 데이터는 변함이 없게 된다.
Hibernate를 사용하고 Service 레이어에서 Transaction을 사용하기 때문에 Hibernate Session 관련 문제가 발생할 수 있기 때문이다.
그래서 Session이 살아 있는 상태에서 1-N 관계가 Fetch 속성이 Lazy라도 object.getXXX 하면 select 문을 날리게 된다.
이 때 select 된 object와 해당 테이블에 직접 select 해서 가져온 object가 동일한 pk를 가진 object들이 겹치기 때문에 변경을 하게 되면 Exception이 발생하게 된다.
그래서 혹시나 하고 Cabinet 오브젝트에 Doors를 재 설정할 수 있게 만들었더니 깔끔하게 해결이 되었다.

public void resetDoors(List<Door> doors) {
        this.doors.clear();
        this.doors.addAll(doors);
}

이 걸로 해결이다.

서비스 레이어는 다음과 같다.
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public Cabinet updateCabinet(Cabinet entity) {
        Order[] orders = new Order[] {Order.asc("id.doorCode")};
        Criterion criterion = Restrictions.eq("cabinet.cabinetCode", entity.getCabinetCode());
        List<Door> listDoors = doorDAO.findByCriteriaOrder(orders, criterion);
       
        for (Door door : listDoors) {
            if (door.getId().getDoorCode() > entity.getIntDoorCount()) {
                door.setIsDeleted(true);
            } else {
                door.setIsDeleted(false);
            }
        }
       
        entity.resetDoors(listDoors);
       
        cabinetDAO.makeSaveOrUpdate(entity);

        return entity;
}

잘 해결되어서 다행이다.
아직 Hibernate가 서툴러서, DB 설계도 서툴러서 생기는 문제인데...
아주 많이 더욱더 공부해야 겠다.
신고
Trackback 0 Comment 0


티스토리 툴바