Baur & King a dit dans son livre:Pourquoi Hibernate génère-t-il un CROSS JOIN pour une jointure implicite d'une association @ManyToOne?
Implicite sont toujours dirigées jointures le long many-to-one ou one-to-one, jamais par une association valeur est une collection.
[P 646, Ch 14]
Mais quand je fais cela dans le code qu'il génère un CROSS JOIN au lieu d'une INNER JOIN.
Le mappage est à partir de Member2
(plusieurs-à-un) ->CLub
.
Mais Club2
n'a aucune information sur les membres et Member2
possède une clé étrangère de Club2.
Ma requête est
// Implicit: Find all UK club member who is female
Transaction t1 = HibernateUtil.begin();
Query query =
HibernateUtil.getSession().createQuery("From Member2 m where m.club2.country = 'UK' ");
List<Member2> memList = query.list();
for (Member2 m : memList)
System.out.println(m);
HibernateUtil.end(t1);
Et, Hibernate génère la requête SQL suivante:
Hibernate:
select
member2x0_.member_id as member_i1_1_,
member2x0_.club_id as club_id5_1_,
member2x0_.member_age as member_a2_1_,
member2x0_.member_name as member_n3_1_,
member2x0_.member_sex as member_s4_1_
from
TBL_MEMBER2 member2x0_ cross
join
TBL_CLUB2 club2x1_
where
member2x0_.club_id=club2x1_.club_id
and club2x1_.country='UK'
Hibernate:
select
club2x0_.club_id as club_id1_0_0_,
club2x0_.club_name as club_nam2_0_0_,
club2x0_.country as country3_0_0_
from
TBL_CLUB2 club2x0_
where
club2x0_.club_id=?
aaa 25 m
bbb 28 f
Club2.java
package com.lilu.de.onetomany.uni.other;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity
@Table(name = "TBL_CLUB2")
public class Club2 {
@GeneratedValue(generator = "pkey_Club2", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "pkey_Club2", initialValue = 1000, allocationSize = 10,
sequenceName = "seq_pkey_Club2")
@Id
private int club_id;
private String club_name;
private String country;
// private Set Member2 = new HashSet();
public Club2() {
super();
}
public Club2(String cname, String ccountry) {
this.club_name = cname;
this.country = ccountry;
}
@Override
public String toString() {
String temp = club_name + " " + country + " ";
// Iterator<Member2> iter = Member2.iterator();
// String mems = null;
// while (iter.hasNext()) {
// mems += iter.next();
// }
// temp += "\n" + mems;
return temp;
}
public int getClub_id() {
return club_id;
}
public void setClub_id(int club_id) {
this.club_id = club_id;
}
public String getClub_name() {
return club_name;
}
public void setClub_name(String club_name) {
this.club_name = club_name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
/*
* public Set<Member2> getMember2() { return Member2; }
*
* public void setMember2(Set<Member2> Member2) { this.Member2 = Member2; }
*/
}
Member2.java
package com.lilu.de.onetomany.uni.other;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity
@Table(name = "TBL_MEMBER2")
public class Member2 {
@GeneratedValue(generator = "pkey_member2", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "pkey_member2", sequenceName = "seq_pkey_member2")
@Id
private int member_id;
private String member_name;
private int member_age;
private char member_sex;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "club_id")
private Club2 club2;
public Member2() {
super();
}
public Member2(String mname, int age, char sex) {
this.member_name = mname;
this.member_age = age;
this.member_sex = sex;
}
public Club2 getClub2() {
return club2;
}
public void setClub2(Club2 club2) {
this.club2 = club2;
}
@Override
public String toString() {
return member_name + " " + member_age + " " + member_sex;
}
public String getMember_name() {
return member_name;
}
public void setMember_name(String member_name) {
this.member_name = member_name;
}
public int getMember_age() {
return member_age;
}
public void setMember_age(int member_age) {
this.member_age = member_age;
}
public char getMember_sex() {
return member_sex;
}
public void setMember_sex(char member_sex) {
this.member_sex = member_sex;
}
public int getMember_id() {
return member_id;
}
public void setMember_id(int member_id) {
this.member_id = member_id;
}
}
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ Copyright (c) 2010, Red Hat Inc. or third-party contributors as
~ indicated by the @author tags or express copyright attribution
~ statements applied by the authors. All third-party contributions are
~ distributed under license by Red Hat Inc.
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, write to:
~ Free Software Foundation, Inc.
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost:5432/hibernatedb1</property>
<property name="connection.username">postgres</property>
<property name="connection.password">ani155</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<!-- Names the annotated entity class -->
<mapping class="com.lilu.de.onetomany.uni.other.Club2"/>
<mapping class="com.lilu.de.onetomany.uni.other.Member2"/>
<!-- <mapping class="com.apal.mapping.onetoone.User"/> -->
</session-factory>
</hibernate-configuration>
Test.java
package com.lilu.de.onetomany.uni.other;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Test {
public static void main(String[] args) {
Test test = new Test();
// test.setup();
test.SelectQuery1Implicit();
// test.SelectQuery2ExplicitFromClause();
// test.SelectQuery3JoinFetch();
// test.SelectQuery4ThetaJoin();
}
private void SelectQuery1Implicit() {
// Implicit: Find all UK club member who is female
Transaction t1 = HibernateUtil.begin();
Query query =
HibernateUtil.getSession().createQuery("From Member2 m where m.club2.country = 'UK' ");
List<Member2> memList = query.list();
for (Member2 m : memList)
System.out.println(m);
HibernateUtil.end(t1);
}
private void setup() {
Transaction t1 = HibernateUtil.begin();
Club2 c1 = new Club2("MulaRougne", "UK");
Member2 m1 = new Member2("aaa", 25, 'm');
Member2 m2 = new Member2("bbb", 28, 'f');
m1.setClub2(c1);
m2.setClub2(c1);
HibernateUtil.getSession().save(c1);
HibernateUtil.getSession().save(m1);
HibernateUtil.getSession().save(m2);
Club2 c2 = new Club2("Queen's Club", "UK");
Club2 c3 = new Club2("Disney", "USA");
Member2 m3 = new Member2("ccc", 32, 'm');
Member2 m4 = new Member2("ddd", 23, 'm');
m3.setClub2(c3);
m4.setClub2(c3);
HibernateUtil.getSession().save(m3);
HibernateUtil.getSession().save(m4);
HibernateUtil.getSession().save(c2);
HibernateUtil.getSession().save(c3);
/*
* Club2 c1 = new Club2("MulaRougne", "UK"); Club2 c2 = new Club2("Queen's Club", "UK"); Club2
* c3 = new Club2("Disney", "USA");
*
* Member2 m1 = new Member2("aaa", 25, 'm'); Member2 m2 = new Member2("bbb", 28, 'f'); Member2
* m3 = new Member2("ccc", 32, 'm'); Member2 m4 = new Member2("ddd", 23, 'm'); Member2 m5 = new
* Member2("ee", 30, 'f');
*
* c1.getMember2().add(m1); c1.getMember2().add(m2); c1.getMember2().add(m3);
*
* c2.getMember2().add(m4); c2.getMember2().add(m5);
*
* HibernateUtil.getSession().save(c2); HibernateUtil.getSession().save(m4);
* HibernateUtil.getSession().save(m5);
*
* HibernateUtil.getSession().save(c1); HibernateUtil.getSession().save(m1);
* HibernateUtil.getSession().save(m2); HibernateUtil.getSession().save(m3);
*/
HibernateUtil.end(t1);
}
private static class HibernateUtil {
private static SessionFactory factory;
private static Session session;
static {
factory = new Configuration().configure().buildSessionFactory();
}
public static Session getSession() {
return session;
}
public static Transaction begin() {
session = factory.openSession();
return session.beginTransaction();
}
public static void end(Transaction tran) {
tran.commit();
}
}
}
avez essayé HQL comme: 'De Member2 comme m interne rejoindre m.club2 comme c où c.country = 'UK'' – Amogh
Quel est le problème? La clause where a 'où member2x0_.club_id = club2x1_.club_id', donc Hibernate récupère correctement du club du membre. Tout va bien. –
Oui Hib récupère correctement les données mais il effectue une jointure croisée à la place d'une jointure interne. Nous savons que cross join fait un produit croisé qui est lent et consomme de la mémoire. Ne devrait pas faire une jointure interne ?? C'est ma préoccupation .. Merci pour vos réponses. – anirban