在下面的代码中,我希望发生n+1
查询问题,但它没有发生。
的 User.java :
import java.util.*;
public class User {
private long userId;
private String firstName;
private Set phones;
public User() {
System.out.println("0-arg constructor :User");
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public Set getPhones() {
return phones;
}
public void setPhones(Set phones) {
this.phones = phones;
}
}
PhoneNumber.java :
public class PhoneNumber {
private String numberType;
private long phone;
private long id;
User parent;
public PhoneNumber() {
System.out.println("0-arg constructor :PhoneNumber");
}
// write getXxx(),setXxx() methods (4 sets)
public void setId(long id) {
this.id = id;
}
public long getId() {
return id;
}
public String getNumberType() {
return numberType;
}
public void setNumberType(String numberType) {
this.numberType = numberType;
}
public long getPhone() {
return phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
public void setParent(User parent) {
this.parent = parent;
}
public User getParent() {
return parent;
}
}
User.hbm.xml :
<hibernate-mapping>
<class name="User"
table="USER_TABLE" >
<id name="userId"
column="USER_ID"/>
<property name="firstName"
column="FIRST_NAME"/>
<set name="phones"
table="PHONE_NUMBERS" cascade="all"
lazy="true">
<key column="UNID"/>
<one-to-many
class="PhoneNumber"/>
</set>
</class>
</hibernate-mapping>
phoneNumber.hbm :
<hibernate-mapping>
<class name="PhoneNumber" table="PHONE_NUMBERS" >
<id name="phone" column="PHONE"/>
<property name="numberType" column="NUMBER_TYPE"/>
<property name="id" column="UNID" insert="false" update="false"/>
<many-to-one name="parent" class="User" column="UNID2" cascade="all"/>
</class>
</hibernate-mapping>
hibernate.cfg :
<session-factory>
<property
name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</
property>
<property
name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:xe</prope
rty>
<property
name="hibernate.connection.username">system</property>
<property
name="hibernate.connection.password">oracle123</property>
<property
name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<mapping resource="user.hbm.xml"/>
<mapping resource="phoneNumber.hbm.xml"/>
</session-factory>
HQLClient.java :
import org.hibernate.*;
import org.hibernate.cfg.*;
import java.util.*;
public class HQLJoinsClient {
public static void main(String[] args) {
try {
Configuration conf = new Configuration().configure();
SessionFactory factory = conf.buildSessionFactory();
Session ses = factory.openSession();
String hql = "from User ";
Query q = ses.createQuery(hql);
List l = q.list();
System.out.println("++++++++++++++++++" + l.size()
+ "+++++++++++++");
for (int i = 0; i < l.size(); ++i) {
User u1 = (User) l.get(i);
System.out
.println("\n\n\nParent----------------------------------------------------------------->");
System.out.print("user id: " + u1.getUserId());
System.out.println("FirstName " + u1.getFirstName());
Set s = u1.getPhones();
if (s != null) {
Iterator it = s.iterator();
while (it.hasNext()) {
PhoneNumber p1 = (PhoneNumber) it.next();
System.out.println("\nchild---->");
System.out.print("Number Type=" + p1.getNumberType());
System.out.print("Phone Number=" + p1.getPhone());
System.out.println("User id=" + p1.getId());
}// inner while
}// if
}
ses.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出如下:
INFO: schema update complete Hibernate: select user0_.USER_ID as USER1_0_, user0_.FIRST_NAME as FIRST2_0_ from USER_TABLE user0_
0-arg constructor :User 0-arg constructor :User 0-arg constructor :User ++++++++++++++++++3+++++++++++++++++++++++++ Parent-----------------------------------------------------------------> user id: 102FirstName ravi Hibernate: select phones0_.UNID as UNID1_, phones0_.PHONE as PHONE1_, phones0_.PHONE as PHONE1_0_, phones0_.NUMBER_TYPE as NUMBER2_1_0_, phones0_.UNID as UNID1_0_, phones0_.UNID2 as UNID4_1_0_ from PHONE_NUMBERS phones0_ where phones0_.UNID=? 0-arg constructor :PhoneNumber 0-arg constructor :PhoneNumber 0-arg constructor :PhoneNumber child----> Number Type=resPhone Number=81818181User id=102 child----> Number Type=officePhone Number=71717171User id=102 child----> Number Type=homePhone Number=91919191User id=102 Parent-----------------------------------------------------------------> user id: 103FirstName jayendra Hibernate: select phones0_.UNID as UNID1_, phones0_.PHONE as PHONE1_, phones0_.PHONE as PHONE1_0_, phones0_.NUMBER_TYPE as NUMBER2_1_0_, phones0_.UNID as UNID1_0_, phones0_.UNID2 as UNID4_1_0_ from PHONE_NUMBERS phones0_ where phones0_.UNID=? 0-arg constructor :PhoneNumber 0-arg constructor :PhoneNumber child----> Number Type=resPhone Number=3748329382User id=103 child----> Number Type=homePhone Number=538432342User id=103 Parent-----------------------------------------------------------------> user id: 104FirstName mike Hibernate: select phones0_.UNID as UNID1_, phones0_.PHONE as PHONE1_, phones0_.PHONE as PHONE1_0_, phones0_.NUMBER_TYPE as NUMBER2_1_0_, phones0_.UNID as UNID1_0_, phones0_.UNID2 as UNID4_1_0_ from PHONE_NUMBERS phones0_ where phones0_.UNID=? 0-arg constructor :PhoneNumber 0-arg constructor :PhoneNumber child----> Number Type=homePhone Number=238349384User id=104 child----> Number Type=mobilePhone Number=9455682832User id=104
我希望每个电话号码记录到用户ID会有单独的select语句,但是对于3个Phonenumber-1 userid,有一个select语句[而不是(3 + 1)]。为什么会这样?
谢谢!
答案 0 :(得分:0)
您的地图中存在一些问题。
首先,one-to-many
和many-to-one
位于由一列表示的关系数据库中。两端都是同一列,所以这是错误的:
// class name="User"
<set name="phones" table="PHONE_NUMBERS"
cascade="all" lazy="true">
<key column="UNID"/> // this column must be same
<one-to-many class="PhoneNumber" />
</set>
// class name="PhoneNumber"
...
<many-to-one name="parent" class="User"
column="UNID2" // as this column
cascade="all"/>
两个列值必须定位到同一列
其次,您遇到1 + N问题。用户有一个 SELECT,但是为他们的电话选择了3个。这是标准的1 + N问题。
解决方案是使用:
小引用:
使用批量提取,如果访问一个代理,Hibernate可以加载几个未初始化的代理。批量提取是延迟选择提取策略的优化。您可以通过两种方式配置批量提取:在类级别和集合级别。
更容易理解批量提取类/实体。请考虑以下示例:在运行时,您在会话中加载了25个Cat实例,并且每个Cat都有一个对其所有者的引用,即Person。 Person类使用代理映射,lazy =&#34; true&#34;。如果您现在遍历所有猫并在每个猫上调用getOwner(),默认情况下,Hibernate将执行25个SELECT语句来检索代理所有者。您可以通过在Person:
的映射中指定批量大小来调整此行为
<class name="Person" batch-size="10">...</class>
因此,我们应该在集合中使用此设置:
<set name="phones" table="PHONE_NUMBERS" batch-size="25"
cascade="all" lazy="true">
我建议在每个类映射中使用它:
<class name="PhoneNumber" table="PHONE_NUMBERS" batch-size="25">