我的定位:中高级人才(框架熟练、Java语法精通、数据库会用、Linux会用、中间件会用、有大数据经验!)
开始,我以为自己什么都知道。后来发现,其实我什么都不知道。

hibernate07--关联映射

单向的一对多关联

创建对应的实体类以及映射文件

package cn.bdqn.bean;
/**
 * 
 * @author 小豆腐
 *街道对应的实体类
 *
 *单向的多对一关联
 */
public class Street {
    
    private Integer id;
    private String name;
    //多个街道  属于  一个区县
    private    District district;  //对应的区县
    
    
    
    public District getDistrict() {
        return district;
    }
    public void setDistrict(District district) {
        this.district = district;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Street(Integer id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public Street() {
        super();
    }
    @Override
    public String toString() {
        return "Street [id=" + id + ", name=" + name + "]";
    }
    
    

}

 

<?xml version="1.0"?>
<!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.bdqn.bean">
  <class name="Street">
       <id name="id"> 
          <generator class="assigned"/><!-- 手动给主键赋值 -->
       </id>  
       <property name="name"/>
       <!-- 配置多对一关联
       name:对应的是  本类中 关联关系的属性名
       column:对应数据库中 两个表的  外键!
       class:关联的实体类-->
       <many-to-one name="district" column="districtId" class="District"/> 
  </class>
</hibernate-mapping>
package cn.bdqn.bean;
/**
 * @author 小豆腐
 *
 *区县的实体类
 */
public class District {

    private Integer id;
    private String name;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public District(Integer id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public District() {
        super();
    }
    @Override
    public String toString() {
        return "Street [id=" + id + ", name=" + name + "]";
    }
    
    

}
<?xml version="1.0"?>
<!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.bdqn.bean">
    <class name="District">
       <id name="id"> 
          <generator class="assigned"/><!-- 手动给主键赋值 -->
       </id>  
       <property name="name"/>
  </class>
</hibernate-mapping>

需要在hibernate.cfg.xml文件中 配置映射文件

 

 

测试类

Session session=null;
        Transaction transaction=null;
        
        
        //获取session  开启事务
        @Before
        public  void  before(){
            session=HibernateSessionUtil.getCurrentSession();
            transaction= session.beginTransaction();
        }
    
        
        /**
         * 测试单向的多对一的关联
         * 
         * 创建对应的区县    新增几个区县   以备后续使用
         */
        @Test
        public   void   testAdd(){
            District district=new District(3, "区县3");
            session.save(district);  //保存
            transaction.commit();  //提交事务
        }
        
    
    
    //新增 街道的同时 给街道对应的区县赋值
    @Test
    public   void   test01(){
        //创建一个街道
        Street street=new Street();
        street.setId(1);
        street.setName("街道1");
        //给对应的区县赋值
        District district= (District) session.load(District.class, 1);
        street.setDistrict(district);
        session.save(street);  //保存
        transaction.commit();  //提交事务   只会产生一条sql  insert
    }
    
    //修改 街道对应的区县 
    @Test
    public   void   test02(){
        //从数据库中获取一个街道
        Street street=(Street) session.load(Street.class, 1);  // 对应的区县是1
        District district=(District) session.load(District.class, 2);  // 区县是2
        //修改
        street.setDistrict(district);  // 不需要 update  因为两个对象都是持久化对象
        //提交事务
        transaction.commit();
    }
    
    //删除 街道对应的区县 
    @Test
    public   void   test03(){
        //从数据库中获取一个街道
        Street street=(Street) session.load(Street.class, 1);  // 对应的区县是2
        //修改
        street.setDistrict(null);  
        //提交事务
        transaction.commit();
    }
    

双向的一对多关联就是在单向多对一的基础上增加一个单向的一对多!

修改District代码 一对多关联

 

package cn.bdqn.bean;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 小豆腐
 *
 *区县的实体类
 *  一对多的关联关系
 */
public class District {

    private Integer id;
    private String name;
    // 一个区县 有  多个街道
    private List<Street> streets=new ArrayList<>();
    
    
    public List<Street> getStreets() {
        return streets;
    }
    public void setStreets(List<Street> streets) {
        this.streets = streets;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public District(Integer id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public District() {
        super();
    }
    @Override
    public String toString() {
        //如果写成streets   会出现 堆栈溢出的异常!
        return "District [id=" + id + ", name=" + name + ", streets=" + streets.size()
                + "]";
    }
    
    
    
    

}

修改District.hbm.xml文件代码

<?xml version="1.0"?>
<!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.bdqn.bean">
    <class name="District">
       <id name="id"> 
          <generator class="assigned"/><!-- 手动给主键赋值 -->
       </id>  
       <property name="name"/>
       <!-- 设置一对多  
       name:本类中的关联属性名  集合的名称
       column: 就是数据库表中的外键
       order-by="id desc" 按照 街道的id 进行 降序排列
       inverse:是由谁来维护表与表之间的关系! 默认是false!(维护)    true(不维护)
       -->
       <bag name="streets" cascade="all" inverse="true">
        <key column="districtId"/>
         <one-to-many class="Street"/>
       </bag>
  </class>
</hibernate-mapping>

在测试类中增加代码

 

/**
     * 创建几个街道      测试 双向的一对多关联
     */
    @Test
    public   void   test04(){
        Street street=new Street();
        street.setId(4);
        street.setName("街道4");
        //给对应的区县赋值
        District district= (District) session.load(District.class, 1);
        street.setDistrict(district);
        session.save(street);  //保存
        //提交事务
        transaction.commit();
    }
    
    //根据区县  获取所管辖的街道
    @Test
    public  void  test05(){
    District district=(District) session.load(District.class, 1);
        List<Street> streets = district.getStreets();
        for (Street street : streets) {
            System.out.println(street);
        }
    }
    /**
     * 根据区县  获取所管辖的街道       根据街道的编号 降序排列
     * 01.只需要在 bag节点中  增加 order-by属性  =  id   desc
     */
    @Test
    public  void  test06(){
        District district=(District) session.load(District.class, 1);
        List<Street> streets = district.getStreets();
        for (Street street : streets) {
            System.out.println(street);
        }
    }
    /**
     * 02.使用hql语句
     */
    @Test
    public  void  test07(){
        String  hql="from  Street s where districtId=:id  order by s.id desc";
        //创建query对象
        Query query = session.createQuery(hql);
        //给参数赋值
        query.setParameter("id", 1);   //区县编号是1
        //遍历结果集
        List<Street> list = query.list();
        for (Street street : list) {
            System.out.println(street);
        }
    }
    
    /**
     * cascade属性:定义的是关系两端 对象到对象的级联关系!
     *  必须是  双向的一对多关联!
     *  
     *  常用的属性值:
     *  01.none:默认值!当session操作当前对象的时候,忽略关联的属性!
     *  02.save-update:当session调用save,saveorUpdate以及update()的时候!
     *                会级联的保存和修改当前对象以及对象关联的属性!
     *          001.去区县的xml文件中 的 bag节点 增加 cascade属性!    
     *          002.直接运行以下代码 
     *  03.delete: 当session调用 delete()的时候,会级联删除所关联的对象  !
     *  04.all: 包括了save-update和delete!
     * 
     * 添加区县的同时 添加街道
     */
    @Test
    public  void  test08(){
        //创建区县
        District district=new District(4, "区县4");
        //创建街道
        Street street1=new Street(5, "街道5");
        Street street2=new Street(6, "街道6");
        Street street3=new Street(7, "街道7");
        //给区县的街道赋值
        district.getStreets().add(street1);
        district.getStreets().add(street2);
        district.getStreets().add(street3);
        //保存区县
        session.save(district);   //发现 保存了 区县  但是 没有保存对应的街道!
        transaction.commit();
        /**
         * 程序执行之后的结果:
         *  Hibernate: insert into District (name, id) values (?, ?)
            Hibernate: update Street set districtId=? where id=?
            Hibernate: update Street set districtId=? where id=?
            Hibernate: update Street set districtId=? where id=?
         */
        
        /**
         * 在xml文件中设置了 cascade="save-update" 之后的结果
         * 
         * 问题:虽然级联保存成功了!
         *     但是有多余update语句!
         *     为什么会出现多余的?   两个对象都在维护彼此之间的关系!
         * 
         *  Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?
            Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?
            Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?
            Hibernate: insert into District (name, id) values (?, ?)
            Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)
            Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)
            Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)
            Hibernate: update Street set districtId=? where id=?
            Hibernate: update Street set districtId=? where id=?
            Hibernate: update Street set districtId=? where id=?
         */
    }
    
    
    /**
     * cascade="delete"    xml中的配置
     * 删除 区县 的同时 删除 街道!
     */
    @Test
    public  void  test09(){
        District  district= (District) session.load(District.class, 1);
        //获取三个街道
        Street  street1= (Street) session.load(Street.class, 2);
        Street  street2= (Street) session.load(Street.class, 3);
        Street  street3= (Street) session.load(Street.class, 4);
        session.delete(district);
        transaction.commit();
        /**
         *  Hibernate: update Street set districtId=null where districtId=?
            Hibernate: delete from Street where id=?
            Hibernate: delete from Street where id=?
            Hibernate: delete from Street where id=?
            Hibernate: delete from District where id=?
         */
    }
    
    
    
    /**
     * 针对于 多余的sql语句 解决办法!
     * 
     * 只需要一方来维护表之间的关系!
     * inverse属性:
     *   01.默认是false(由我维护!)
     *   02.inverse=true:这一方不维护关系!(不与数据库交互)
     *  
     *   
     *  不能都维护,也不能都 不维护! 这个时候关键是谁来维护这个关系?
     *  双向的一对多! 
     *  hibernate:规定多的一端来维护关系,那么必须在一的一方设置 inverse=true:
     */
    @Test
    public  void  test10(){
        //创建区县
        District district=new District(4, "区县4");
        //创建街道
        Street street1=new Street(5, "街道5");
        Street street2=new Street(6, "街道6");
        Street street3=new Street(7, "街道7");
        //给区县的街道赋值
        district.getStreets().add(street1);
        district.getStreets().add(street2);
        district.getStreets().add(street3);
        //保存区县
        session.save(district);   //发现 保存了 区县  但是 没有保存对应的街道!
        transaction.commit();
        /**
         * 
         * 发现  没有了 update语句!
         * Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?
            Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?
            Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?
            Hibernate: insert into District (name, id) values (?, ?)
            Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)
            Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)
            Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)
         */
    }

 

posted @ 2017-06-29 11:29  想太多先森  阅读(157)  评论(0编辑  收藏  举报