5.hibernate映射(一对一)

一对一关系分以下几种:

  • 单向主键一对一
  • 双向主键一对一
  • 单向外键一对一
  • 双向外键一对一

在此先介绍统一用的实体类:

package entity;

import java.util.Date;


/**
 * 单向one to one,User指向Group
 * 主键关联
 * @author arkulo
 *
 */

public class User {
    private int id;
    private String userName;
    private String passWd;
    private Date addtime;
    private IdCard ic;
    



    public IdCard getIc() {
        return ic;
    }

    public void setIc(IdCard ic) {
        this.ic = ic;
    }

    public Date getAddtime() {
        return addtime;
    }

    public void setAddtime(Date addtime) {
        this.addtime = addtime;
    }

    public User(){}



    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWd() {
        return passWd;
    }

    public void setPassWd(String passWd) {
        this.passWd = passWd;
    }

    
}

package entity;

/**
 * 身份证,不需要指向User
 * @author arkulo
 *
 */
public class IdCard {
    private int id;
    private String idCard;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getIdCard() {
        return idCard;
    }
    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

}

一、单向主键一对一

User.hbm.xml

    
    
    
        
            
                
                
                    
                    ic
                
            
                    
            
            
            
            
            
    

idcard.hbm.xml

    
    
    
        
            
                
            
            
            
    

单元测试:

    package entity;
    
    import java.util.Date;
    
    import org.hibernate.classic.Session;
    
    import junit.framework.TestCase;
    import util.hibernateUtil;
    
    /**
     * 一对一关联分为两大类:主键关联,唯一外键关联 
     * 一对一关联还有方向之分:单向和双向
     * 
     * 本项目是一对一单向主键关联方式
     * 
     * @author arkulo
     *
     */
    
    public class TestOneToOne extends TestCase {
    
        /**
         * 单向主键one to one,添加数据,注意主键是否需要提前生成
         * 因为是一对一,主键外键关联是做在user表上的,因此,要测试是否提前生成idcard的主键
         */
    
        public void test1() {
            Session session = null;
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
    
                IdCard idcard = new IdCard();
                idcard.setIdCard("123456789");
                // 这里不用saveidcard,user保存的时候会一起save
    
                User user = new User();
                user.setUserName("王蕊");
                user.setPassWd("123456");
                user.setAddtime(new Date());
                user.setIc(idcard);
    
                session.save(user);
    
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            } finally {
                hibernateUtil.closeSession(session);
            }
    
            // 读取关联数据,get函数能不能在读取User的时候,把idCard也读取出来,用不同的session,避免一级缓存
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
    
                User user = (User) session.get(User.class, 1);
                System.out.println("用户名:" + user.getUserName());
                // 上面user的查询是直接发出一条sql语句,但是并没有关联查询idcard,当执行到下面这句话的时候,因为可以从user中
                // 获得idcard的主键id,因此又发出了一条sql,条件是id的去查询idcard
                System.out.println("身份证:" + user.getIc().getIdCard());
    
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            } finally {
                hibernateUtil.closeSession(session);
            }
    
        }
    
        /**
         * 如果要删除idcard数据,user数据会怎么样?
         * 请先用test1函数做数据初始化,初始化后运行此函数,请将hibernate.hbm2ddl.auto改为update
         */
        public void test2() {
            // 在这里调用一下初始化数据的test1函数
            test1();
            System.out.println("----------------------------------");
            Session session = null;
    
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
    
                // 因为有外键约束存在,如果构造直接构造一个瞬时状态的IdCard对象,然后直接去删除,系统会报错,提示
                // 有外键约束,不能删除
                // IdCard ic = new IdCard();
                // ic.setId(1);
                // session.delete(ic);
    
                // 这里我们模拟构造一个顺势状态的User,看是否能够直接删除
                // 这里没有构造idcard对象,单独删除user成功,idcard记录没有删除
                // User user = new User();
                // user.setId(1);
                // session.delete(user);
    
                // 这里我们再来试一下,构造了idcard,看能不能关联删除
                // 这里也没有删除idcard
                // IdCard ic = new IdCard();
                // ic.setId(1);
                //
                // User user = new User();
                // user.setId(1);
                // user.setIc(ic);
                // session.delete(user);
    
                // 这里我们设置一下映射文件中的级联方式,让他的级联方式变成delete,看看能不能删除idcard
                // 只有user拥有了id,idcard也拥有了id,加上级联关系,然后删除user的时候,才会连锁删除idcard
                IdCard ic = new IdCard();
                ic.setId(1);
    
                User user = new User();
                user.setId(1);
                user.setIc(ic);
                session.delete(user);
    
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            } finally {
                hibernateUtil.closeSession(session);
            }
    
        }
    
    }

二、双向主键一对一

    
    
    
        
            
                
                
                    
                    ic
                
            
                    
            
            
            
            
            
    

    
    
    
        
            
                
            
            
            
            
            
            
            
    

单元测试:

    package entity;
    
    import java.util.Date;
    
    import org.hibernate.classic.Session;
    
    import junit.framework.TestCase;
    import util.hibernateUtil;
    
    
    /**
     * 一对一关联分为两大类:主键关联,唯一外键关联
     * 一对一关联还有方向之分:单向和双向
     * 
     * 本项目是双向主键一对一关联,测试目的如下:
     * 1. 双向关联插入?如果是在idcard中添加user对象,是不是保存idcard对象,就算是保存了user对象
     * 2. 不管是读取那个对象的数据,都会带出关联的数据,不需要单独去查询
     * 3. 删除,是否可以反向删除,例如删除idcard,然后会不会也删除user
     * @author arkulo
     *
     */
    
    public class TestOneToOne extends TestCase {
    
        // 1. 双向数据插入的测试
        public void test1() {
            Session session = null;
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
                IdCard ic = new IdCard();
                ic.setIdCard("123456789");
    
                User user = new User();
                user.setUserName("王蕊");
                user.setAddtime(new Date());
                user.setPassWd("123323");
                user.setIc(ic);
    
                ic.setUser(user);
    
                // 单独保存idcard不会级联保存user数据,只会单独保存idcard的数据
                // session.save(ic);
    
                // 如果单独保存user对象,会连天idcard对象一起保存
                session.save(user);
    
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            } finally {
                hibernateUtil.closeSession(session);
            }
        }
    
        /**
         * 2. 读取数据,由user是否能关联查处
         */
        public void test2() {
            // 这里需要调用一下数据初始化函数test
            test1();
            System.out.println("-----------------------------------------");
            Session session = null;
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
                // 从user角度读取数据,先发出一条sql语句,查询user,然后打印username,查询idcard的sql语句这时候并没有发出
                User user = (User) session.get(User.class, 1);
                System.out.println("用户名:" + user.getUserName());
                // 在这里要用到idcard的数据的时候,才发出了查询idcard的sql语句(left out join)
                System.out.println("身份证号码:" + user.getIc().getIdCard());
    
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            } finally {
                hibernateUtil.closeSession(session);
            }
    
            // 这里通过查询idcard,看能不能级联查处user数据,在不同的session里面测试,避免一级缓存
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
                IdCard ic = (IdCard) session.get(IdCard.class, 1);
                // 这种情况下,一次性采用连表查询left out join将两张表一起取出来了
                System.out.println("用户名:" + ic.getUser().getUserName());
                System.out.println("身份证编号:" + ic.getIdCard());
    
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            } finally {
                hibernateUtil.closeSession(session);
            }
    
        }
    
        /**
         * 3. 删除的时候会不会有级联效果
         */
        public void test3() {
            test1();
            System.out.println("-----------------------------");
            Session session = null;
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
    
                // 构造一个user瞬时对象,然后直接删除
                IdCard ic = new IdCard();
                ic.setId(1);
    
                User user = new User();
                user.setId(1);
                user.setIc(ic);
    
                ic.setUser(user);
    
                // 如果单独删除user,系统会自动级联删除idcard
                session.delete(user);
    
                // 如果单独删除idcard,系统报错,提示有外键约束,不能删除
                // session.delete(ic);
    
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            } finally {
                hibernateUtil.closeSession(session);
            }
    
        }
    }

三、单向外键一对一

    
    
    
        
            
                
            
                    
            
            
            
            
            
    

    
    
    
        
            
                
            
            
            
    

单元测试:

    package entity;
    
    import java.util.Date;
    
    import org.hibernate.classic.Session;
    
    import junit.framework.TestCase;
    import util.hibernateUtil;
    
    
    /**
     * 单向外键一对一关联
     * 
     * 1. 添加数据,级联保存,保存user的时候,是否能同时保存idcard
     * 2. 查询数据,查询user的时候,是否能查处idcard
     * 3. 删除数据,删除user,是否能级联删除idcard,如果把级联规则改掉,删除user,是否可以不删除idcard
     * @author arkulo
     *
     */
    
    
    public class TestOneToOne extends TestCase {
        
    //  添加数据
        public void test1()
        {
            Session session = null;
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
                
    //          外间单向关联,首先需要保存idcard,如果只是保存user的时候,会提示错误,user中的外间关联字段会没有值
    //          也就是说,单独保存user的时候,不能一并保存idcard对象
                IdCard ic = new IdCard();
                ic.setIdCard("1234567");
                session.save(ic);
                
                User user = new User();
                user.setUserName("王蕊");
                user.setAddtime(new Date());
                user.setIc(ic);
                
                session.save(user);
                
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            }finally{
                hibernateUtil.closeSession(session);
            }
        }
    
        
    //  查询数据,是否能实现查询user的时候,一次性关联查询出idcard
        public void test2()
        {
    //      初始化数据
            test1();
            System.out.println("-------------------------------------");
            Session session = null;
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
                
    //          采用load查询方式
                User user = (User)session.load(User.class, 1);
    //          这里单独的发出一条sql语句,去查询user表,并没有查询idcard
                System.out.println("用户名:"+user.getUserName());
    //          这里单独的发出了一条sql语句,where条件是id,去查询idcard
                System.out.println("身份证编号:"+user.getIc().getIdCard());
                            
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            }finally{
                hibernateUtil.closeSession(session);
            }
        }
        
    //  删除操作
        public void test3()
        {
            test1();
            System.out.println("-----------------------------");
            Session session = null;
            
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
                
    //          自定义一个idcard瞬时对象
                IdCard ic = new IdCard();
                ic.setId(1);
                
    //          自定义一个顺势对象user
                User user = new User();
                user.setId(1);
                user.setIc(ic);
                
    //          在cascade默认情况下,单独删除user,不会级联删除idcard的!!
    //          在cascade设为delete情况下,单独删除user, 会级联删除idcard
                session.delete(user);
                
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            }finally{
                hibernateUtil.closeSession(session);
            }
        }
        
        
    }

四、双向外键一对一

    
    
    
        
            
                
            
                    
            
            
            
            
            
    

    
    
    
        
            
                
            
            
            
            
            
    

单元测试:

    package entity;
    
    import java.util.Date;
    
    import org.hibernate.classic.Session;
    
    import junit.framework.TestCase;
    import util.hibernateUtil;
    
    /**
     * 双向一对一外键关联
     * 1. 在设置映射的时候,idcard的one to one映射加上property-ref的作用
     * 2. 新增,新增之后查看idcard和user之间的关联关系
     * 3. 查询,双向关联是基于对象之间的,不是数据库表之间的,数据库表里还是user表中加字段,关联idcard
     * 4. 删除,双向关联,删除idcard会删除user吗?
     * @author arkulo
     *
     */
    
    
    public class TestOneToOne extends TestCase {
    //  新增数据
        public void test1(){
            Session session = null;
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
                
                IdCard ic = new IdCard();
                ic.setIdCard("12345678");
                
                User user = new User();
                user.setUserName("王蕊");
                user.setPassWd("242424");
                user.setAddtime(new Date());
                user.setIc(ic);
                
                ic.setUser(user);
                
    //          这里我们来尝试一下,如果我们要保存idcard,能否一起保存use对象
    //          单独保存idcard对象,只能保存idcard,不会级联保存user
    //          如果在idcard的映射文件中,设置cascade属性,然后单独保存idcard,系统会报错
    //          session.save(ic);
                
    //          单独保存user对象也是不行的,因为这时候idcard还没有保存,没有主键可以关联
    //          因此需要先保存idcard,然后再保存user
                session.save(ic);
                session.save(user);
                
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            }finally{
                hibernateUtil.closeSession(session);
            }
        }
        
        /**
         * 读取数据:
         * 1. 是否能从user级联查询出idcard
         * 2. 是否能从idcard级联查询出user
         */
        public void test2(){
            test1();
            System.out.println("-------------------------------------------");
            Session session = null;
    //      第一种情况
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
    //          这里也是两条语句,在get函数的时候立即发出一条sql语句,查询user表
    //          在打印身份证编号的时候发出第二条sql语句,关联查询user表和idcard表,得出idcar的数据
                User user = (User)session.get(User.class, 1);
                System.out.println("用户名:"+user.getUserName());
                System.out.println("身份证编号:"+user.getIc().getIdCard());
                            
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            }finally{
                hibernateUtil.closeSession(session);
            }
            System.out.println("------------------------------");
    //      第二种情况
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
    //          这里一条sql语句,把user表和idcard一起查询出来
                IdCard ic = (IdCard)session.get(IdCard.class, 1);
                System.out.println("用户名:"+ic.getUser().getUserName());
                System.out.println("身份证编号:"+ic.getIdCard());
                            
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            }finally{
                hibernateUtil.closeSession(session);
            }       
        }
        
        /**
         * 删除测试
         * 1. 在不设置cascade的情况下,删除user,会不会级联删除idcard
         * 2. 在设置了级联操作下,阐述idcard,会不会删除user
         */
        public void test3(){
            test1();
            System.out.println("------------------------------");
            Session session = null;
            
            try {
                session = hibernateUtil.getSession();
                session.beginTransaction();
                
                IdCard ic = new IdCard();
                ic.setId(1);
    
                User user = new User();
                user.setId(1);
                user.setIc(ic);
                ic.setUser(user);
                
    //          1. 在默认不设置cascade的情况下,删除user是不会级联删除idcard的
    //          2. 在默认不设置cascade的情况下,删除idcard会报错,提示外键关联,不能随意删除
    //          3. cascade设置为delete情况下,删除user会级联删除idcard
    //          4. cascade设置为delete情况下,删除idcard会报错,提示外键关联,不能随意删除
                session.delete(user);
    //          session.delete(ic);
                
                
                session.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                session.getTransaction().rollback();
            }finally{
                hibernateUtil.closeSession(session);
            }
            
        }
        
    
    }

你可能感兴趣的:(5.hibernate映射(一对一))