1

在下面的代码中,我预计n+1会发生查询问题,但它没有发生。 用户.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;
    }
}

电话号码.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;
    }

}

用户.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>

电话号码.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>

休眠.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 会有单独的选择语句,但是对于 3 个电话号码 - 1 个用户 ID 有一个选择语句 [而不是 (3+1)]。为什么会这样?

谢谢!

4

1 回答 1

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 问题。用户有一个选择,但他们的电话有 3 个选择。这是标准的 1 + N 问题。

解决方案是使用:

20.1.5。使用批量获取

小引用:

使用批量获取,如果访问一个代理,Hibernate 可以加载多个未初始化的代理。批量抓取是对惰性选择抓取策略的优化。有两种方法可以配置批量获取:在类级别和集合级别。

类/实体的批量获取更容易理解。考虑以下示例:在运行时,您在 Session 中加载了 25 个 Cat 实例,每个 Cat 都有对其所有者的引用,即 Person。Person 类使用代理lazy="true" 进行映射。如果您现在遍历所有猫并在每个猫上调用 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">
于 2014-09-13T07:44:41.063 回答