hibernate一对多demo

实体类:

package com.xiangshuai.hibernate;

 

import java.util.HashSet;

import java.util.Set;

 

/**

 * 顾客类

 * */

public class Customer {

         privateInteger id;

         privateString cname;

         privateSet<Order> orders=new HashSet<Order>();

         publicInteger getId() {

                  returnid;

         }

         publicvoid setId(Integer id) {

                  this.id= id;

         }

         publicString getCname() {

                  returncname;

         }

         publicvoid setCname(String cname) {

                  this.cname= cname;

         }

         publicSet<Order> getOrders() {

                  returnorders;

         }

         publicvoid setOrders(Set<Order> orders) {

                  this.orders= orders;

         }

         @Override

         publicString toString() {

                  return"Customer [id=" + id + ", cname=" + cname + ",orders=" + orders + "]";

         }

        

}

 

package com.xiangshuai.hibernate;

/**

 * 订单类

 * */

public classOrder {

    private Integer id;

   privateString oname;

   privateCustomer customer;

    public Integer getId() {

        return id;

    }

    public void setId(Integer id) {

        this.id = id;

    }

    public String getOname() {

        return oname;

    }

    public void setOname(String oname) {

        this.oname = oname;

    }

    public Customer getCustomer(){

        return customer;

    }

    public void setCustomer(Customer customer) {

        this.customer = customer;

    }

    @Override

    public String toString() {

        return "Order [id="+ id + ", oname="+ oname+ "]";

    }

 

   

}

实体类对应的XML文件

一的一方:Customer.hbm.xml

<?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">

   <!-- ORM元数据  表对象关系映射文件

    package : 配置该配置文件中类所在的包.  -->

 <hibernate-mapping package="com.xiangshuai.hibernate" >

    <class name="Customer" table="t_customer"  >

        <!-- 如果类属性 namecolumn一致可以只定name -->

        <id name="id"column="id" length="255">

            <generator class="native"></generator>

        </id>  

        <property name="cname"></property>

        <!-- 一对多关系用 set配置set标签中将inverse设为ture则此xml对应的类放弃维护外键,

        Customer放弃维护外键,实际开发也一般是一的一方放弃维护外键关系

        默认是flase,如果一的一方经常要维护cid外键,那么这里就不要设置,默认就好

        <keycolumn="cid"> column类名这里表示Order对应的表中的列名(表外键字段cid)cid

        <one-to-manyclass="Order"/>cid表对应的类

        如果inverse设为true 也就是一的一方不负责维护外键cid的创建等等,那么在用session.sava(customer)

        虽然因为设置了cascade="save-update,delete"但也只会保存order对象中已有属性,而不会保存order对象中

        没有的属性cid,因此在执行session.sava(customer)前必须执行 order1.set(customer),order1.set(customer),

        order这个多的一方维护外键,先将customer保存到对象中以生成cid这样 session.sava(customer)执行后t_order给的

        cid值才不会为null

        delete却可以直接 session.delete(customer)在删除customer的同时删除customer所拥有的所有订单-->

        <set name="orders" inverse="true"cascade="save-update,delete" lazy="false">

            <key column="cid"></key>

            <one-to-many class="Order"/>

        </set>

    </class>

 </hibernate-mapping>

 

多的一方:Order.hbm.xml

<?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">

   <!-- ORM元数据  表对象关系映射文件

    package : 配置该配置文件中类所在的包.  -->

 <hibernate-mapping package="com.xiangshuai.hibernate" >

    <class name="Order" table="t_order"  >

           <id name="id"column="id" length="255">

            <generator class="native"></generator>

        </id>  

        <property name="oname"></property>

        <!-- 多的一方直接用<many-to-one 标签配置与一的一方的关系即可

        nameOrder的属性名 customet,class="Customer" 这个name"customer"对应的类  ,column对应的外键名即多

        的一方的外键名和一一方set中的<key column="cid"></key>一致-->

        <many-to-one name="customer" class="Customer"column="cid"></many-to-one>

    </class>

 </hibernate-mapping>

 

将实体类对应的xml文件mapperhibernate.cfg.xml

<?xml version="1.0"encoding="UTF-8"?>

<!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>

        <!-- property 元素用于配置Hibernate中的属性

            :

          -->

          <!--hibernate.connection.driver_class : 连接数据库的驱动  -->

        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

          <!--hibernate.connection.username : 连接数据库的用户名 -->

        <property name="hibernate.connection.username">root</property>

          <!--hibernate.connection.password : 连接数据库的密码 -->

        <property name="hibernate.connection.password">root</property>

          <!--hibernate.connection.url : 连接数据库的地址,路径 -->

        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/demo</property>

       

        <!-- show_sql: 操作数据库时,向控制台打印sql语句 -->

        <property name="show_sql">true</property>

        <!-- format_sql: 打印sql语句前,会将sql语句先格式化  -->

        <property name="format_sql">true</property>

        <!-- hbm2ddl.auto: 生成表结构的策略配置

             update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构.

                    如果存在表结构,并且表结构与实体一致,那么不做修改

                    如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.

             create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)

            create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.

             validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.

          -->

        <property name="hbm2ddl.auto">update</property>

       

        <!-- 数据库方言配置

         org.hibernate.dialect.MySQLDialect (选择最短的)

         -->

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

       

       

       

        <!-- hibernate.connection.autocommit: 事务自动提交  -->

        <property name="hibernate.connection.autocommit">true</property>

        <!-- Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession-->

        <property name="hibernate.current_session_context_class">thread</property>

        <!-- 引入ORM 映射文件

            填写src之后的路径

         -->

        <mapping resource="com/xiangshuai/hibernate/Customer.hbm.xml"/>

        <mapping resource="com/xiangshuai/hibernate/Order.hbm.xml"/>

       

    </session-factory>

</hibernate-configuration>

 

测试类:

package com.xiangshuai.test;

 

import java.util.HashSet;

import java.util.Set;

 

import org.hibernate.Query;

import org.hibernate.SQLQuery;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.classic.Session;

import org.junit.Test;

 

import com.xiangshuai.hibernate.Customer;

import com.xiangshuai.hibernate.Order;

 

public class COdemo {

         privateConfiguration  conf=null;

         SessionFactorysessionFactory=null;

         Sessionsession =null;

          @Test

    public void demoSave(){

             /* 因为Customer.hbm.xml<setname="orders" inverse="true"cascade="save-update,delete">中

              * 因为inverse="true"设为true所以 customer不负责维护外键,

              * 因为设置了级联sava-update所以只要执行session.sava(customer)就可以保存orers到数据库

              * 删除也是可以直接执行session.delete(customer)就可以级联删除customer下的所有order

              * */

                   session=getSession();Transaction tr =session.beginTransaction();

                   Order order1 = new Order(); Order order2 = newOrder();Customer customer1 = new Customer();

                   order1.setOname("订单1");order1.setCustomer(customer1);order2.setOname("订单2");order2.setCustomer(customer1);

                   Set<Order> orders=newHashSet<Order>();orders.add(order1);orders.add(order2);

                   customer1.setCname("小明");customer1.setOrders(orders);

                   session.save(customer1);

                   tr.commit();closeStream(sessionFactory,session);

    }

          @Test

          public void delete(){

                   /*Customer.hbm.xml<setname="orders" inverse="true"cascade="save-update,delete">

                    * 因为设置了级联所以直接执行session.delete(customer)就可以级联删除customer下的所有order*/

                   session=getSession();Transaction tr =session.beginTransaction();

                   Query query = session.createQuery("fromCustomer where id=?").setInteger(0, 4);

                   Customer customer = (Customer)query.uniqueResult();

                   session.delete(customer);

                   tr.commit();closeStream(sessionFactory,session);

          }

          @Test

          public void update(){

                   session=getSession();Transaction tr =session.beginTransaction();

                   Query query = session.createQuery("fromCustomer where id=?").setInteger(0, 5);

                   /**

                    * 因为在Customer.hbm.xml的set标签中并没有设lazy="false"(默认为true),所以在执行完query.uniqueResult()

                    * 只会向数据库将Customer查出来(执行的sql为 Hibernate:select customer0_.id as id0_,customer0_.cname as cname0_

   from t_customer customer0_ wherecustomer0_.id=?),只有当真正要用到order时才会再次向数据库发sql,但如如下代码

    在执行    System.out.println(customer)时因为session已经关闭,所以无法发sql会报

   org.hibernate.LazyInitializationException: failed to lazily initialize acollection of role: com.xiangshuai.hibernate.Customer.orders, no session orsession was closed

         at这个错        

    **/

                   Customer customer = (Customer)query.uniqueResult();

                   customer.setCname("小明改2");

                   session.update(customer);

                   tr.commit();closeStream(sessionFactory,session);

                   System.out.println(customer);

          }

          @Test

          public void lazyselect(){

                   /*在Customer.hbm.xml的set标签中设lazy="false"(默认为true)--<setname="orders" inverse="true"cascade="save-update,delete" lazy="false">

                    * 那么会向数据库查customer对象时将orders也会一并查出

                    * 如执行完 .uniqueResult()会查出customer的同时查出其customer对象的属性Set<Order>order对象的记录

                    * sql如下--Hibernate:

   select *  from t_customer  where id=?

               Hibernate:

   select orders0_.cid as cid0_1_,orders0_.id as id1_, orders0_.id asid1_0_,orders0_.oname as oname1_0_,

       orders0_.cid as cid1_0_  from  t_order orders0_ where orders0_.cid=?

       而且此时执行customer.toString也不会再报错---这里也注意 customer和order类重写 toString方法不能两个都将对方属性toString中

       否则会死循环造成java.lang.StackOverflowError 内存溢出

                    * */

                   session=getSession();Transaction tr =session.beginTransaction();

                   //链式操作

                   Customer customer = (Customer)session.createSQLQuery("select * from t_customer whereid=?").addEntity(Customer.class).setInteger(0, 5).uniqueResult();

                   /*SQLQuery createSQLQuery =session.createSQLQuery("select * from t_customer where id=?");

                   SQLQuery addEntity =createSQLQuery.addEntity(Customer.class);

                   Query c1 = addEntity.setInteger(0, 4);

                   Customer c = (Customer) c1.uniqueResult();*/

                  tr.commit();closeStream(sessionFactory, session);

                  System.out.println(customer);

          }

          public Session getSession() {

                          //1读取配置文件

                           conf = new Configuration().configure();

                          //2根据配置 创建Factory

                          sessionFactory= conf.buildSessionFactory();

                          //3通过获得操作数据库的session对象

                          session= sessionFactory.openSession();

                          returnsession;

                  }

                   public void closeStream(SessionFactorysessionFactory,Session session){

                             if(session!=null){

                                     session.close();

                             }

                             if(sessionFactory!=null){

                                      sessionFactory.close();

                             }

                   }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值