Hibernate04_延迟加载一对多

x33g5p2x  于2021-12-25 转载在 其他  
字(7.1k)|赞(0)|评价(0)|浏览(347)

Hibernate04_延迟加载

一对多查一
以 Customer和Orders为例:

  • Customer
@Data
public class Customer {
	private Integer id;
	private String name;
	private Set<Orders> orders;
}
  • Orders
@Data
public class Orders {
	private Integer id;
	private String name;
	private Customer customer;
}
  • Customer.hbm.xml
    注:一对多中一的延迟加载是默认开启的
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.blu.entity.Customer" table="customer">
		<id name="id" type="java.lang.Integer">
			<column name="id"></column>
			<generator class="identity"></generator>
		</id>
		<property name="name" type="java.lang.String">
			<column name="name"></column>
		</property>
		<set name="orders" table="orders" lazy="true">
			<key column="cid"></key>
			<one-to-many class="com.blu.entity.Orders"></one-to-many>
		</set>
	</class>

</hibernate-mapping>
  • Orders.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.blu.entity.Orders" table="orders">
		<id name="id" type="java.lang.Integer">
			<column name="id"></column>
			<generator class="identity"></generator>
		</id>
		<property name="name" type="java.lang.String">
			<column name="name"></column>
		</property>
		<many-to-one name="customer" class="com.blu.entity.Customer" column="cid"></many-to-one>
	</class>

</hibernate-mapping>
  • 测试:
public static void main(String[] args) {
	Configuration configuration = new Configuration().configure();
	SessionFactory sessionFactory = configuration.buildSessionFactory();
	Session session = sessionFactory.openSession();
	Customer customer = session.get(Customer.class,5);
	System.out.println(customer);
	session.close();
}

测试结果报错,原因是:

System.out.println(customer);

打印Customer对象时,嵌套打印了Orders,然后打印Orders时又嵌套打印了Customer,不断嵌套直至内存溢出 StackOverflowError

解决办法是修改对象的 toString() 方法!

  • Customer
@Getter
@Setter
public class Customer {
	private Integer id;
	private String name;
	private Set<Orders> orders;
	
	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + "]";
	}	
}
  • Orders
@Getter
@Setter
public class Orders {
	private Integer id;
	private String name;
	private Customer customer;
	
	@Override
	public String toString() {
		return "Orders [id=" + id + ", name=" + name + "]";
	}
	
}
  • 测试1:
public static void main(String[] args) {
	Configuration configuration = new Configuration().configure();
	SessionFactory sessionFactory = configuration.buildSessionFactory();
	Session session = sessionFactory.openSession();
	Customer customer = session.get(Customer.class,5);
	System.out.println(customer);
	session.close();
}
  • 结果:
    只发送了一条SQL
Hibernate: 
    select
        customer0_.id as id1_1_0_,
        customer0_.name as name2_1_0_ 
    from
        customer customer0_ 
    where
        customer0_.id=?
Customer [id=5, name=张三]
  • 测试2:
public static void main(String[] args) {
	Configuration configuration = new Configuration().configure();
	SessionFactory sessionFactory = configuration.buildSessionFactory();
	Session session = sessionFactory.openSession();
	Customer customer = session.get(Customer.class,5);
	System.out.println(customer.getOrders());
	session.close();
}
  • 结果:
    发送了两条SQL
Hibernate: 
    select
        customer0_.id as id1_1_0_,
        customer0_.name as name2_1_0_ 
    from
        customer customer0_ 
    where
        customer0_.id=?
Hibernate: 
    select
        orders0_.cid as cid3_2_0_,
        orders0_.id as id1_2_0_,
        orders0_.id as id1_2_1_,
        orders0_.name as name2_2_1_,
        orders0_.cid as cid3_2_1_ 
    from
        orders orders0_ 
    where
        orders0_.cid=?
[Orders [id=2, name=订单1]]
  • 关闭延迟加载
lazy="false"
  • 测试1:
public static void main(String[] args) {
	Configuration configuration = new Configuration().configure();
	SessionFactory sessionFactory = configuration.buildSessionFactory();
	Session session = sessionFactory.openSession();
	Customer customer = session.get(Customer.class,5);
	System.out.println(customer);
	session.close();
}
  • 结果:
    发送了两条SQL
Hibernate: 
    select
        customer0_.id as id1_1_0_,
        customer0_.name as name2_1_0_ 
    from
        customer customer0_ 
    where
        customer0_.id=?
Hibernate: 
    select
        orders0_.cid as cid3_2_0_,
        orders0_.id as id1_2_0_,
        orders0_.id as id1_2_1_,
        orders0_.name as name2_2_1_,
        orders0_.cid as cid3_2_1_ 
    from
        orders orders0_ 
    where
        orders0_.cid=?
Customer [id=5, name=张三]

注:lazy除了可以设置true和false,还可以设置为extra,extra是比true更为懒惰(智能)的一种加载方式。

例:查询Customer对象,打印Customer对象对应的orders集合的长度。

测试:

Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class,5);
System.out.println(customer.getOrders().size());
session.close();
lazy="true"

结果:
根据customer的id = order的cid,查出所有的order并添加到集合里,然后计算集合的长度。

Hibernate: 
    select
        customer0_.id as id1_1_0_,
        customer0_.name as name2_1_0_ 
    from
        customer customer0_ 
    where
        customer0_.id=?
Hibernate: 
    select
        orders0_.cid as cid3_2_0_,
        orders0_.id as id1_2_0_,
        orders0_.id as id1_2_1_,
        orders0_.name as name2_2_1_,
        orders0_.cid as cid3_2_1_ 
    from
        orders orders0_ 
    where
        orders0_.cid=?
1
lazy="extra"

结果:
根据customer的id = order的cid,通过cid直接通过count方法计算order的数量。

Hibernate: 
    select
        customer0_.id as id1_1_0_,
        customer0_.name as name2_1_0_ 
    from
        customer customer0_ 
    where
        customer0_.id=?
Hibernate: 
    select
        count(id) 
    from
        orders 
    where
        cid =?
1

一对多查多
注:一对多中多的延迟加载是默认关闭的
测试:

public static void main(String[] args) {
	Configuration configuration = new Configuration().configure();
	SessionFactory sessionFactory = configuration.buildSessionFactory();
	Session session = sessionFactory.openSession();
	Orders orders = session.get(Orders.class, 2);
	System.out.println(orders);
}

结果:发送了两条SQL

Hibernate: 
    select
        orders0_.id as id1_2_0_,
        orders0_.name as name2_2_0_,
        orders0_.cid as cid3_2_0_ 
    from
        orders orders0_ 
    where
        orders0_.id=?
Hibernate: 
    select
        customer0_.id as id1_1_0_,
        customer0_.name as name2_1_0_ 
    from
        customer customer0_ 
    where
        customer0_.id=?
Orders [id=2, name=订单1]

修改Orders.hbm.xml( lazy=“proxy”

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.blu.entity.Orders" table="orders">
		<id name="id" type="java.lang.Integer">
			<column name="id"></column>
			<generator class="identity"></generator>
		</id>
		<property name="name" type="java.lang.String">
			<column name="name"></column>
		</property>
		
		<many-to-one name="customer" class="com.blu.entity.Customer" column="cid" lazy="proxy"></many-to-one>
		
	</class>

</hibernate-mapping>

再次测试:(此时只发送了一条SQL)

Hibernate: 
    select
        orders0_.id as id1_2_0_,
        orders0_.name as name2_2_0_,
        orders0_.cid as cid3_2_0_ 
    from
        orders orders0_ 
    where
        orders0_.id=?
Orders [id=2, name=订单1]

相关文章