2010-08-01 12 views
8

B varlığına sahip A varlığına sahibim ve B, AOToTone çift yönlü ilişkisiyle A'ya sahiptir. ŞimdiHazırda bekletme için iki sorgusu neden bir @OneToOne iki yönlü derleme?

i A kayıtları findall zaman, B böyle bir şey katılmak sol dış birleşim ile iki sorgu gerçekleştirmek hazırda bekletme:

select a.id, a.id_b, a.field1, b.id, b.field1 from A as a, B as b left outer join b ON b.id=a.id_b; 
select a.id, a.id_b, a.field1, b.id, b.field1 from A as a, B as b left outer join b ON b.id=a.id_b WHERE b.id=? 

İlk sorgu yük A ve B alanları ve Tamam, ama neden gerçekleştirmek A yeniden yüklemek için ikinci sorgu? Bu sorgunun B içeriğinin B olarak yükleneceğini düşünüyorum, ancak bu A, B'yi içeren A olan bir obezdir. Bu nedenle, ilk sorguyla zaten yüklü, doğru değil mi?

- DÜZENLEME -

A işletmesi:

@Entity 
public class A implements Serializable{ 
    // id and other ecc ecc 
    @OneToOne 
    @JoinColumn(name="id_b") 
    B b; 
} 

Varlık B:

@Entity 
public class B implements Serializable{ 
    // id and other ecc ecc 
    @OneToOne(mappedBy="b") 
    A a; 
} 

Bu bir ihtiyaç iki sorgular durum ve findAll olduğunu .. . niye ya?

cevap

6

Oral, eğer A ve B payı her iki tarafın kullanılarak birleştirilir aynı birincil anahtar sütunu onların birincil anahtar, yapmanız yerine

@Entity 
public class A implements Serializable { 

    private MutableInt id = new MutableInt(); 

    private B b; 

    public void setIdAsMutableInt(MutableInt id) { 
     this.id = id; 
    } 

    @Id 
    @GeneratedValue 
    public Integer getId() { 
     return id.intValue(); 
    } 

    public void setId(Integer id) { 
     this.id.setValue(id); 
    } 

    /** 
     * Any ToOne annotation, such as @OneToOne and @ManyToOne, is EARGELY loaded, by default 
     */ 
    @OneToOne(fetch=FetchType.LAZY) 
    @PrimaryKeyJoinColumn 
    @Cascade(CascadeType.SAVE_UPDATE) 
    public B getB() { 
     return b; 
    } 

    public void setB(B b) { 
     b.setIdAsMutableInt(id); 

     this.b = b; 
    } 

} 

@PrimaryKeyJoinColumn kullanmak Ve B Bildirimi gerekir mappedBy niteliği nedeniyle @PrimaryKeyJoinColumn gerekmez

@Entity 
public class B implements Serializable { 

    private MutableInt id = new MutableInt(); 

    private A a; 

    public void setIdAsMutableInt(MutableInt id) { 
     this.id = id; 
    } 

    @Id 
    public Integer getId() { 
     return id.intValue(); 
    } 

    public void setId(Integer id) { 
     this.id.setValue(id); 
    } 

    @OneToOne(fetch=FetchType.LAZY) 
    @PrimaryKeyJoinColumn 
    public A getA() { 
     return a; 
    } 

    public void setA(A a) { 
     this.a = a; 
    } 

} 
Tamsayı bir şekilde Hem A ve bir değişmez Tip çünkü

Hadi Testi yerine tamsayı

A a = new A(); 
B b = new B(); 

a.setB(b); 

/** 
    * b property will be saved because Cascade.SAVE_UPDATE 
    */ 
Serializable id = session.save(a); 

b = (B) session 
     .createQuery("from B b left join fetch b.a where b.id = :id") 
     .setParameter("id", id) 
     .list() 
     .get(0); 

Assert.assertEquals(b.getId(), b.getA().getId()); 

Bildirim I (a tamsayı özelliğiyle kapsüllü ) bir MutableInt alanı kullanın (İstersen test edebilir) B grubu hisse AYNI atanan id

Ama A ve B onların birincil anahtar Dışındaki kullanılarak birleştirilir, sen @JoinColumn ve mappedBy kullanmalıdır (iki yönlü bir ilişki, sağ) olarak

izler B Tablo herhangi bir yabancı anahtar içermediğinden
@Entity 
public class A implements Serializable { 

    private Integer id; 

    private B b; 

    @Id 
    @GeneratedValue 
    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    /** 
     * mappedBy="a" means: Look at "a" field/property at B Entity. If it has any assigned value, join us Through B_ID foreign key column 
     */ 
    @OneToOne(fetch=FetchType.LAZY, mappedBy="a") 
    /** 
     * Table A has a foreign key column called "B_ID" 
     */ 
    @JoinColumn(name="B_ID") 
    @Cascade(CascadeType.SAVE_UPDATE) 
    public B getB() { 
     return b; 
    } 

    public void setB(B b) { 
     this.b = b; 
    } 

} 

Ve B

@Entity 
public class B implements Serializable { 

    private Integer id; 

    private A a; 

    public void setIdAsMutableInt(MutableInt id) { 
     this.id = id; 
    } 

    @Id 
    @GeneratedValue 
    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    @OneToOne(fetch=FetchType.LAZY) 
    public A getA() { 
     return a; 
    } 

    public void setA(A a) { 
     this.a = a; 
    } 

} 

sahibi yan B kullanarak

A a = new A(); 
B b = new B(); 

/** 
    * Set up both sides 
    * Or use some kind of add convenience method 
    */ 
a.setB(b); 
b.setA(a); 

/** 
    * b property will be saved because Cascade.SAVE_UPDATE 
    */ 
Serializable id = session.save(a); 

b = (B) session 
     .createQuery("from B b left join fetch b.a where b.id = :id") 
     .setParameter("id", id) 
     .list() 
     .get(0); 

test etmek için, sen ortaya çıkar İki seçme ifadeleri alacak Tablo A'u işaret eden sütun Ancak,

"sol katılmak A'dan ab getir nerede a.id =: id" A onun B_ID yabancı anahtar sütunu

kullanarak kendi katıldı B almak için nasıl bilir çünkü sadece bir select ifadesi alacak

+0

Teşekkür ederim! Çok kapsamlı! – blow

0

Haritanız tam olarak nasıl görünüyor?

sizin A ve B sınıfları doğru Hazırda A örneği ilk A aynı örneğidir B tarafından işaret olduğunu söyleyebilirim hashCode() ve equals() böylece uygulamak mı?

İki yönlü bire bir eşlemeyi modellemek istediğiniz gibi geliyor - bunu gerçekleştirmek için önerilen yöntemleri görmek için the section in the manual on this'a bakın.

+0

Gönderiyi düzenledim. Evet, sadece ID'ye dayalı çok basit bir eşitlik ve hashCode uygulamasına sahibim. Tüm girişimlerim bu uygulama ile bir AbstractEntity uzanır. – blow

İlgili konular