2011-01-05 3 views
0

많은 Person 엔티티에 매핑되는 House 엔티티가 있다고 가정 해 보겠습니다. 나는 20 명의 거주자가있는 기존의 하인을 적재한다. 나중에 코드에서Hibernate가 saveOrUpdate를 호출 할 때 원치 않는 SELECT를 수행 중임

beginTransaction(); 
House house = houseDao.find(1L); 
commitTransaction(); 

, 나는 그 집에 새로운 사람을 추가 할 수 있습니다

... 
List<Person> people = house.getPeople(); 
people.add(new Person("Dilbert")); 
.... 

을 내가 전화 할 때 :

session.saveOrUpdate(house); 

Hibernate는 21 개 쿼리를 수행 : 1을에 하우스를 선택하고 하우스에있는 기존 인원을 각각 20 명씩 선택합니다.

나는이 상황에서 데이터베이스에 엄청난 피해를주지 않으면 서 새 사람을 집에 추가 할 수 있도록 내가해야 할 일은 무엇인가?

이것은 모두 동일한 세션 내에서 수행됩니다.

답변

3

실제로 개체 정의에 많은 것을주지 않았기 때문에 몇 가지 가정을 할 것입니다.

지금
@Entity 
public class House implements Serializable { 
    @Id 
    private int id; 

    @OneToMany(mappedBy="house") 
    private Set<Person> people; 

    ... rest of your class 
} 


@Entity 
public class Person implements Serializable { 

    @Id 
    private int id; 

    @ManyToOne(targetEntity=House.class) 
    private House house; 

    @Column(name="person_name") 
    private String name 

    ... rest of your class 

    public Person(House house, String name) { 
     this.house = house; 
     this.name = name; 
    } 
} 

코드 :

사람에게

  1. 홈은 집 같이 정의된다

이 있는지 확인 한 집에 속할 수 많은

  • 사람에게 하나입니다
    beginTransaction(); 
    House house = houseDao.find(1L); 
    commitTransaction() 
    
    
    ... your magic 
    
    Person person = new Person(house,"Dilbert"); 
    
    session.saveOrUpdate(person); 
    

    시험에서 당신이 부모/자식 관계를 가지고 일할 때 (그다지 중요하지 않더라도 많은 것에서 많은 것까지), 자녀를 통해 관계를 형성 할 수 있습니다. 나는 일반적으로 부모를 통해 담요 업데이트를하는 것에서 멀리 떨어져 있습니다. 당신의 예에서는 그것이 머리를 많이 차지하는 것을 보았습니다. 수천 개의 기록이있는 곳에서 일을 시작하면 불가능 해집니다.

    다른 모델은 모델에 따라 목록에 대한 특수 효과를 미묘하게 변경하는 것입니다. 예제 :

    @Entity 
    public class House implements Serializable { 
        @Id 
        private int id; 
    
        @OneToMany(mappedBy="house") 
        @Fetch(FetchMode.JOIN) 
        private Set<Person> people; 
    
        ... rest of your class 
    } 
    

    @Fetch는 JPA 스펙의 일부가 아니지만, 집 개체와 모든 사람들을 그랩 것이기 때문에 최대 절전 모드 주석이,이, 모델에 따라하는 것은 큰 성능 향상을 줄 수있는 점을 감안 단일 쿼리에서. 이것은 집과 집에 속한 사람들의 수를 제한하는 경우에 매우 효과적입니다. 매우 큰 결과를 얻는다면 이것은 좋은 상황이 아닐 수도 있습니다. 다음 예가 더 적합 할 수 있습니다.

    @Entity 
    public class House implements Serializable { 
        @Id 
        private int id; 
    
        @OneToMany(mappedBy="house") 
        @Fetch(FetchMode.SUBSELECT) 
        private Set<Person> people; 
    
        ... rest of your class 
    } 
    

    이렇게하면 두 개의 쿼리를 사용하여 모든 개체를 가져옵니다. 하우스 개체에 대한 하나의 쿼리 (또는 쿼리에 따라 집 개체 곱하기) 및 집 개체에 대한 모든 사람들에 대한 하나의 쿼리.

  • +0

    죄송합니다. 제 게시물에 Set과 예제 사용 목록을 사용함을 깨달았습니다. 목록으로 설정에서 전환 할 수 있습니다. – celias

    +0

    가장 좋은 제안은 '집'이 아닌 '사람'을 유지하는 것입니다. +1 –

    +0

    brilliant - 감사합니다. celias. 정확히 내가 무엇을 찾고 있었는지. – digiarnie

    0

    나는 이것이 당신의 문제에 대한 잠재적 인 대답이라고 생각하지만, 아마도 당신이 생각하고있는 정확한 방식은 아닙니다.

    나는 Hibernate가 당신이 원하는 방식으로 동작하도록 만드는 방법을 찾지 못했다. (그것은 세분화 수준이 없다.) 원한다면 직접 코딩 할 수있을 것이라고 확신합니다.DB에 대한 성능 저하가 실제로 걱정된다면 문제를 해결하고 DB에 대한 부하를 최소화하는 방법에 집중하십시오.

    Hibernate에서 DB로 호출을 최적화하는 가장 좋은 방법은 모든 Hibernate 객체 테이블이 색인되도록하는 것이다. Hibernate는 부모 객체의 프라이 머리 키를 사용하여 테이블을 호출한다. 20 개의 쿼리는 인덱스를 검색하고 신속하게 위치 할 경우 DB 처리 시간이 거의 필요하지 않습니다. DB는 이와 같이 많은 트랜잭션을 처리 할 수 ​​있도록 제작되었습니다. 값 비싼 부분은 디스크에 데이터를 배치하고이를 사용하기 위해로드하는 것입니다.

    마지막으로 개체 캐시도 추가합니다. 이로 인해 잠재적으로 DB 로의 왕복을 없애고 프로그램에 많은 I/O 대기 시간을 절약 할 수 있습니다.

    관련 문제