zoukankan      html  css  js  c++  java
  • hibernate 数据关联一对多

    一对多,多对一 (在多的一端存放一的外键)
    但是在实体类中不需要创建这个外键

    // 在一的一方创建Set集合
    public class User {
        
        private Integer id;
        private String username;
        private String password;
        private Set<Address> addressSet;
    }
    //多的一方创建User的对象
    public class Address {
    
        private Integer id;
        private String address;
        private User user;
    }

    在映射文件中也要配置

    一对多的一:User.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">
    <hibernate-mapping package="com.kaishengit.pojo">
        
        <class name="User" table="user">
            <id name="id">
                <generator class="native"/>
            </id>
            
            <property name="username"/>
            <property name="password"/>
            <!-- name是类中属性的名字,站在User的角度这是一对多,所以是one-to-many
                 然后指定对应的多指的是哪个类.
                 <key column="userid"/>指维持这种关系的多的这一端(Address)类对应的表中的外键
                 inverse="true"表示放弃关系维护-->
            <set name="addressSet" cascade="delete" inverse="true">
                <key column="userid"/>
                <one-to-many class="Address"/>
            </set>
            
        </class>
    </hibernate-mapping>

    一对多的多:Address.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">
    <hibernate-mapping package="com.kaishengit.pojo">
        
        <class name="Address" table="address">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="address"/>
            <!-- 站在这个角度是多对一many-to-one
                name写对应的属性名,class是对应的类 然后指定外键-->
            <many-to-one name="user" class="User" column="userid"/>
            
        </class>
        
    
    </hibernate-mapping>

    --------------------------------------------------------------------------

    --------------------------------------------------------------------------

    程序的执行

    1.添加

    //  方式1
            User u1 = new User();
            u1.setUsername("u1");
            u1.setPassword("aaa");
            
            Address a1 = new Address();
            a1.setAddress("a1");
            a1.setUser(u1);
            
            Address a2 = new Address();
            a2.setAddress("a2");
            a2.setUser(u1);
        
            /* 如果是先save的u1,就能拿到u1的id
            然后再save a1,a2的时候加入外键中,等于执行了3条sql
            
            
            如果是先save  a1,a2 那么save的结果是没有userid这个外键的
            在save了u1之后会再去update他们(因为在address关联User的时候,user是自由态
            ,当user保存的时候就变成了持久态,User状态发生变化会同步到数据库中,所以address会更新
            ),等于执行了3条sql还有两条update*/
            session.save(u1);
            session.save(a1);
            session.save(a2);
    
    
    
    
    // 所以对于一对多的这种情况,先存1,再存多
    
    
    
     //  方式2 
    
            User u1 = new User();
            u1.setUsername("u1");
            u1.setPassword("aaa");
            
            Address a1 = new Address();
            a1.setAddress("a1");
            
            
            Address a2 = new Address();
            a2.setAddress("a2");
            
            Set<Address> set = new HashSet<Address>();
            set.add(a1);
            set.add(a2);
            user.setAddressSet(set);
    
       // 这样即使是先存1再存多还是5条sql语句 
    
            session.save(u1);
            session.save(a1);
            session.save(a2);

    所以在一对多的时候,关系要让多来维护,save的时候先保存一的再保存多的

    可以在一的配置中inverse="true"放弃关系维护

    2.查询

    // 单表查询user 
            User user = (User) session.get(User.class, 25);
            System.out.println(user.getUsername());
            /* 要使用address了,单表查询address,这个是延迟查询,当使用address的时候再去查
                ,但是这个查询就必须放在session中才能有作用,给xxx.hbm.xml配置
                lazy="false" 就能取消这个延迟查询,不管你用不用address,但是只要你用user我都会查关联user
                的一切比如(address,这个时候就可以放在session外边了因为查询过后已经放入了内存中*/
            Set<Address> set = user.getAddressSet();
            for(Address a : set) {
                System.out.println(a.getAddress());
            }
    
        // 或者反过来用address查询,也都是两条单表查询
            Address a1 = (Address) session.get(Address.class, 17);
            System.out.println(a1.getAddress());
            System.out.println(a1.getUser().getUsername());

    hibernate默认就是这样的单表查询,但是我们可以改成联接查询 -->
    <!-- 添加fetch="join"表示用一条sql语句查询到所有包括关联的..所以只要不是
    你能承受这么多查询,都要使用以前的延迟查询

    <set name="addressSet" cascade="delete" inverse="true" fetch="join">
                <key column="userid"/>
                <one-to-many class="Address"/>
            </set>

    3.级联删除

    配置属性cascade="delete"属性后,默认删除一的时候把关联的多也删除掉 

    <set name="addressSet" cascade="delete" inverse="true">
            <key column="userid"/>
            <one-to-many class="Address"/>
    </set>

    也删除了address 

    User user = (User) session.get(User.class, 26);
    session.delete(user);

    注:

    我们在user中配置了address的Set,在address中配置了user,这叫
    双向配置,实际上我们都是从user找address,很少从address找user,所以address的可以不配置

  • 相关阅读:
    java代码终于过百行了
    团队建设中人员流失的问题
    将析构函数设置为虚函数,并且析构函数可以为纯虚函数
    J2EE学习笔记——JSP使用Fckeditor
    Android ListView的getview()中position错位 重复调用(position重复调用)
    修正Thinkphp 3.2 分页Page类以支持URL路由
    ThinkPHP中_after_update、_before_update等的用法
    ThinkPHP跨控制器调用方法
    Thinkphp 查询条件 and 和 or同时使用即复合查询
    layer弹出图片的问题
  • 原文地址:https://www.cnblogs.com/itliucheng/p/4462900.html
Copyright © 2011-2022 走看看