day36 08-Hibernate抓取策略:批量抓取
package cn.itcast.test; import java.util.List; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import cn.itcast.utils.HibernateUtils; import cn.itcast.vo.Customer; import cn.itcast.vo.Order; /** * Hibernate的抓取策略 * @author zhongzh * */ public class HibernateDemo2 { @Test /* *批量抓取 减少与数据库交互的次数 * 通过订单批量抓取客户: * 需要在客户一端<class>标签上配置batch-size * 批量抓取都是在一的一端配置的 */ public void demo13(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); List<Order> list =session.createQuery("from Order").list(); for (Order order : list) { System.out.println(order.getCustomer().getCname()); } } @Test /* *批量抓取 减少与数据库交互的次数 * 在客户的一端配置 * <set>集合上配置batch-size="3" */ public void demo12(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); List<Customer> list =session.createQuery("from Customer").list(); for (Customer customer : list) { for (Order order : customer.getOrders()) { System.out.println(order.getAddr()); } } } @Test /* * 没有在<many-to-one>标签上配置: * * fetch="select" lazy="proxy" * * 发送多条SQL */ public void demo11(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 在这行发送多条SQL 查询关联对象. Order order = (Order) session.get(Order.class, 1); System.out.println(order.getCustomer().getCname()); tx.commit(); session.close(); } @Test /* * 没有在<many-to-one>标签上配置: * * fetch="select" lazy="false" * * 发送多条SQL */ public void demo10(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 在这行发送多条SQL 查询关联对象. Order order = (Order) session.get(Order.class, 1); System.out.println(order.getCustomer().getCname()); tx.commit(); session.close(); } @Test /* * 没有在<many-to-one>标签上配置: * * fetch="join" lazy="被忽略" * * 发送迫切左外连接 */ public void demo9(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //发送一条迫切左外连接.查询关联对象. Order order = (Order) session.get(Order.class, 1); System.out.println(order.getCustomer().getCname()); tx.commit(); session.close(); } @Test /* * 没有在<many-to-one>标签上配置: * * 发送多条SQL进行查询. * */ public void demo8(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //只会发送一条查询订单的SQL. Order order = (Order) session.get(Order.class, 1); //使用订单的客户对象的时候,又发送一条SQL查询订单关联的客户 System.out.println(order.getCustomer().getCname()); tx.commit(); session.close(); } @Test /* * 在<set>集合上配置 * * fetch="subselect" lazy="true" * * 使用subselect的时候 需要使用query接口进行测试. * * 如果查询一个客户 查询多个客户. * 如果有多个客户: * * select * from orders where cno in (1,2,3); * 如果只有一个客户: * * select * from orders where cno = 1; */ public void demo7(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); List<Customer> list = session.createQuery("from Customer").list(); for (Customer customer : list) { System.out.println(customer.getOrders().size()); } tx.commit(); session.close(); } @Test /* * 在<set>集合上配置 * * fetch="select" lazy="extra" * * lazy:extra:极其懒惰.要订单的数量 */ public void demo6(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class, 1); // select count(*) from orders where cno = ?; System.out.println(customer.getOrders().size()); //发送查询订单的SQL. for (Order order : customer.getOrders()) { System.out.println(order);//使用订单的是时候它才会发送查询订单的SQL. } tx.commit(); session.close(); } @Test /* * 在<set>集合上配置 * * fetch="select" lazy="false" * * lazy:false:关联对象的检索不使用延迟 */ public void demo5(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 发送多条SQL,查询关联对象. Customer customer = (Customer) session.get(Customer.class, 1); // 使用订单的时候又发送一条查询这个客户的订单的SQL System.out.println(customer.getOrders().size()); tx.commit(); session.close(); } @Test /* * 在<set>集合上配置 * * fetch="select" lazy="true" * * lazy:true-使用延迟检索 * * 发送多条SQL,查询关联对象 */ public void demo4(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 发送一条只查询客户的SQL Customer customer = (Customer) session.get(Customer.class, 1); // 使用订单的时候又发送一条查询这个客户的订单的SQL System.out.println(customer.getOrders().size()); tx.commit(); session.close(); } @Test /* * * <set>配置fetch="join" lazy就会被忽略!!!! * * 发送迫切左外连接查询两个表. */ public void demo3(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //直接发送一条迫切左外连接。其实迫切左外连接和左外连接的SQL语句是一样的.只不过封装的对象不一样. //迫切左外连接封装到一个对象里.而普通左外连接封装到一个数组里. //只要一查客户订单就出来了. /* * Hibernate: select customer0_.cid as cid0_1_, customer0_.cname as cname0_1_, orders1_.cno as cno0_3_, orders1_.oid as oid3_, orders1_.oid as oid1_0_, orders1_.addr as addr1_0_, orders1_.cno as cno1_0_ from Customer customer0_ left outer join orders orders1_ on customer0_.cid=orders1_.cno where customer0_.cid=? */ Customer customer = (Customer) session.get(Customer.class, 1); System.out.println(customer.getOrders().size()); tx.commit(); session.close(); } @Test /* * * <set>没有配置fetch 和 lazy情况 * */ public void demo2(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class,1);// 发送查询客户的SQL. //System.out.println(customer.getCname()); System.out.println(customer.getOrders().size());// 使用了客户的订单的时候,才会发送查询订单的SQL. 又发送一条SQL 去查询客户的关联的订单. tx.commit(); session.close(); } @Test /*区分立即检索和延迟检索 * * */ public void demo1(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //立即检索 // /* Customer customer = (Customer) session.get(Customer.class, 1); System.out.println(customer);*/ //延迟检索: // 持久化类如果设置为final 延迟检索就失效了.因为不能生成代理对象 // 在Customer.hbm.xml中在<class>标签上配置lazy="false"不支持延迟检索,就会立即检索. Customer customer = (Customer) session.load(Customer.class, 1);//这是类级别的检索 //System.out.println(customer);//如果这一行注释的话根本就不会发送SQL语句,你执行完了它也不会发送,因为你根本没有 //用到它里面的属性。 //初始化代理对象 发送SQL语句 产生代理对象 那肯定就能拿出来了 //System.out.println(customer.getCname()); //还可以这样来初始化代理对象 Hibernate.initialize(customer);//当你初始化的时候它才会发送SQL语句 tx.commit(); session.close(); } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.itcast.vo"><!-- 如果这里配置了包名下面可以不用写 --> <!-- <hibernate-mapping> --> <!-- <class name="cn.itcast.hibernate3.demo2.Customer" table="customer"> --> <!-- <class name="cn.itcast.vo.Customer" table="customer"> --> <class name="Customer" batch-size="2" table="customer"> <!-- 配置唯一标识 --> <id name="cid" column="cid"> <generator class="native"/> </id> <!-- 配置普通属性 --> <property name="cname" column="cname" length="30"/> <!-- 建立映射 --> <!-- 配置一个集合 <set>的name Customer对象中的关联对象的属性名称. --> <!-- 这里把级联去掉 要最简短的配置 <set name="orders" cascade="save-update" inverse="true"> --> <set name="orders" cascade="save-update" batch-size="2"> <!-- <key>标签中column:用来描述一对多多的一方的外键的名称. --> <key column="cno"></key> <!-- 配置一个<one-to-many>标签中class属性:订单的类的全路径 --> <!-- <one-to-many class="cn.itcast.hibernate3.demo2.Order"/> --> <one-to-many class="cn.itcast.vo.Order"/> </set> </class> <!-- 命名查询的方式 --> <query name="findAll"> from Customer </query> <!-- 这里要写sql语句 <sql-query> </sql-query> --> </hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!-- <class name="cn.itcast.hibernate3.demo2.Order" table="orders"> --> <class name="cn.itcast.vo.Order" table="orders"> <!-- 配置唯一标识 --> <id name="oid" column="oid"> <generator class="native"/> </id> <!-- 配置普通属性 --> <property name="addr" column="addr" length="50"/> <!-- 配置映射 --> <!-- <many-to-one>标签 name :关联对象的属性的名称. column :表中的外键名称. class :关联对象类的全路径 --> <!-- <many-to-one name="customer" column="cno" class="cn.itcast.hibernate3.demo2.Customer"/> --> <many-to-one name="customer" column="cno" class="cn.itcast.vo.Customer"/> </class> </hibernate-mapping>
package cn.itcast.vo; import java.util.HashSet; import java.util.Set; /** * 客户的实体: * @author 姜涛 * */ public class Customer { private Integer cid; private String cname; public Customer() {//无参构造函数 super(); // TODO Auto-generated constructor stub } public Customer(String cname) {//有参构造 super(); this.cname = cname; } // 一个客户有多个订单. private Set<Order> orders = new HashSet<Order>(); public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } //@Override /* public String toString() {//客户这里打印也打印出订单的集合。这是死循环了,所以这里应该去掉一方的打印。 return "Customer [cid=" + cid + ", cname=" + cname + ", orders=" + orders + "]"; return "Customer [cid=" + cid + ", cname=" + cname + "]";//客户这里去掉订单集合的打印 }*/ //测试迫切内连接的封装效果。重写toString()方法 @Override public String toString() { return "Customer [cid=" + cid + ", cname=" + cname + ", orders=" + orders + "]"; } }
package cn.itcast.vo; /** * 订单的实体: * @author 姜涛 * */ public class Order { private Integer oid; private String addr; // 订单属于某一个客户.放置一个客户的对象. private Customer customer; public Integer getOid() { return oid; } public void setOid(Integer oid) { this.oid = oid; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } //@Override /* public String toString() {//订单这边又打印客户了。这是死循环了,所以这里应该去掉一方的打印。 return "Order [oid=" + oid + ", addr=" + addr + ", customer=" + customer + "]"; }*/ //测试迫切内连接的封装效果。重写toString()方法 @Override public String toString() {//两边不能同时打印,不然容易出问题 return "Order [oid=" + oid + ", addr=" + addr + "]"; } }