• hibernate关联关系的crud2


    hibernate关联关系的CRUD操作,解释都在注释里了,讲了fetchType、cascade。

    User类:

    package com.oracle.hibernate;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;
    
    @Entity
    public class User {
    
        private int id;
        private String name;
        private Group  group;
        
        //多对一
        @ManyToOne(cascade={CascadeType.ALL}//, //设置级联
                    //fetch = FetchType.LAZY
                )
        @JoinColumn(name="groupId")//指定外键名称
        public Group getGroup() {
            return group;
        }
        public void setGroup(Group group) {
            this.group = group;
        }
        @Id
        @GeneratedValue
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
    }

    Group类:

    package com.oracle.hibernate;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    
    @Entity
    @Table(name="t_group")//group是mysql的关键字,换个名
    public class Group {
    
        private int id;
        private String name;
        private Set<User> users = new HashSet<User>();
        
        //设置mappedBy和级联
        @OneToMany(mappedBy="group",
                cascade={CascadeType.ALL}//,//级联管增删改,
                
                //fetch=FetchType.EAGER        //一的一方默认为LAZY
                )
        public Set<User> getUsers() {
            return users;
        }
        public void setUsers(Set<User> users) {
            this.users = users;
        }
        @Id
        @GeneratedValue
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
    }

    测试类:

    package com.oracle.hibernate;
    
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.AnnotationConfiguration;
    import org.hibernate.tool.hbm2ddl.SchemaExport;
    import org.junit.AfterClass;
    import org.junit.BeforeClass;
    
    
    public class Test {
    
        private static SessionFactory  sf = null;
        @BeforeClass
        public static void beforeClass(){
            
            try {
                //生成表
                new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
                sf = new AnnotationConfiguration().configure().buildSessionFactory();
            } catch (HibernateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        @org.junit.Test
        public void testSchemaExport(){
            new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
            
        }
        @AfterClass
        public static void afterClass(){
            sf.close();
        }
        
        @org.junit.Test
        public void testSaveUser(){
            
            Session  s = sf.getCurrentSession();
            s.beginTransaction();
            User user = new User();
            user.setName("u1");
            Group g = new Group();
            g.setName("g1");
            user.setGroup(g);
            //s.save(g);默认不会自动保存关联变量,
            //设置cascade后,直接保存user就能把user的group也保存
            s.save(user);
            s.getTransaction().commit();
        }
        
        @org.junit.Test
        public void testSaveGroup(){
            
            Group g = new Group();
            g.setName("g1");
            User u1 = new User();
            u1.setName("u1");
            //必须设定User所属的group,否则在保存user时不会保存g的信息(hibernate不知道属于哪个group啊)
            u1.setGroup(g);
            User u2 = new User();
            u2.setName("u2");
            u2.setGroup(g);
            g.getUsers().add(u1);
            g.getUsers().add(u2);
            
            Session  s = sf.getCurrentSession();
            s.beginTransaction();
            
            s.save(g);
            s.getTransaction().commit();
        }
        
        @org.junit.Test
        public void testGetUser(){
            testSaveGroup();//生成数据
            
            Session  s = sf.getCurrentSession();
            s.beginTransaction();
            /**
             * 默认情况,多的一方的fetchType=Eager,这符合正常思维,比如我们取学生时也会把他的老师取出来。
             * 设置多的一方User里设fetchType=Lazy时(很少这么干),执行下边的代码发出的sql语句是:
             * Hibernate: 
        select
            user0_.id as id2_0_,
            user0_.groupId as groupId2_0_,
            user0_.name as name2_0_ 
        from
            User user0_ 
        where
            user0_.id=?
            不会把一的一方Group给取出来,只有当用到group的时候(如下边的取u.getGroup.getName)才发sql语句把User和group连接查询
             * 
             */
            User u = (User) s.get(User.class,1);
            //取User,默认情况下,不设cascade,也能取出group,这符合平常逻辑。
            System.out.println(u.getName()+u.getGroup().getName());
            s.getTransaction().commit();
            
            //System.out.println(u.getName()+u.getGroup().getName());
            //会报错,因为fetchType为Lazy,用group的时候才发sql语句,而session却关了,所以报错(懒加载错误)
        }
        
        @org.junit.Test
        public void testGetGroup(){
            testSaveGroup();//生成数据
            
            Session  s = sf.getCurrentSession();
            s.beginTransaction();
            //取group一方,fetchType默认为Lazy,执行下边的一句话:
            //不发取user的sql语句,只发取group的信息的sql。不取多的一方,只有用到user信息时才发sql'语句,下边的g.getUsers()XXX
            Group g = (Group) s.get(Group.class,1);
            s.getTransaction().commit();
            //设置fetchType为EAGER,发的sql语句把user也取出来了,所以即使session关了,也能取出User(从内存)而不报错
            System.out.println(g.getName()+g.getUsers());
        }
        
        
        @org.junit.Test
        public void testLoadUser(){
            testSaveGroup();//生成数据
            
            Session  s = sf.getCurrentSession();
            s.beginTransaction();
        //get拿的是User对象,load,拿的是user的代理对象,
            //执行下边的代码不会发sql语句,当getGroup时才发sql语句
            User u = (User) s.load(User.class,1);
            
            //执行此句时先发出sql语句取user,再发sql语句取user和group,发了2条select
            System.out.println(u.getName()+u.getGroup().getName());
            s.getTransaction().commit();        
            
        }
        
        
        @org.junit.Test
        public void testUpdateUser1(){
            testSaveGroup();//生成数据
            
            Session  s = sf.getCurrentSession();
            s.beginTransaction();
        /**
         * 发的sql语句:
         * 因为 u.getName()+u.getGroup().getName()既取了u。name,又取了u.的group的name,所以
         * 发的select语句取了user和group,
         * Hibernate: 
        select
            user0_.id as id2_1_,
            user0_.groupId as groupId2_1_,
            user0_.name as name2_1_,
            group1_.id as id3_0_,
            group1_.name as name3_0_ 
        from
            User user0_ 
        left outer join
            t_group group1_ 
                on user0_.groupId=group1_.id 
        where
            user0_.id=?
            //但是为什么还会发出下边的select 语句呢?因为group的fetchType设的EAGER,
             * 在u.getGroup().getName()的同时,也会发sql语句去取user的信息。所以不能同时两边设EAGER
             * 一般正常人思维去思考:一般:一对多设lazy,多对一设eager。
             * 但是假设一个人有多个权限,可以设一对多为eager。公司机构、部门可以用。
    Hibernate: 
        select
            users0_.groupId as groupId1_,
            users0_.id as id1_,
            users0_.id as id2_0_,
            users0_.groupId as groupId2_0_,
            users0_.name as name2_0_ 
        from
            User users0_ 
        where
            users0_.groupId=?
         * 可以看到先发的select语句取user和group,又取的user()
         */
            User u = (User) s.load(User.class,1);        
            u.setName("user");
            u.getGroup().setName("group");
            System.out.println(u.getName()+u.getGroup().getName());
            s.getTransaction().commit();        
            
        }
        
        
        @org.junit.Test
        public void testUpdateUser2(){
            testSaveGroup();//生成数据
            
            Session  s = sf.getCurrentSession();
            s.beginTransaction();
        
            User u = (User) s.get(User.class,1);            
            s.getTransaction().commit();//关闭session,而u已经在内存中。
            
            u.setName("user");//修改user姓名
            u.getGroup().setName("group");//修改group
            
            Session s2 = sf.getCurrentSession();
            s2.beginTransaction();
            s2.update(u);    //group和user同时更新,user里cascade起的作用
            s2.getTransaction().commit();        
            
        }
        @org.junit.Test
        public void testDeleteUser(){
            testSaveGroup();//生成表user:u1 u1.group: g  u2.group:g   group:g  
            
            Session s = sf.getCurrentSession();
            s.beginTransaction();
            User u  = (User) s.load(User.class, 1);
            // 级联:会把u1删掉,再把u1指向的group:g删了,g删了,他所关联的u2也没了。
            //s.delete(u);
            //解决办法:先解除关联关系,把u的group设成null,再删除
            u.setGroup(null);
            s.delete(u);
            //用hql:
            //s.createQuery(" from User u where u.id = 1");
            s.getTransaction().commit();
        }
        
        @org.junit.Test
        public void testDeleteGroup(){
            testSaveGroup();//生成表user:u1 u1.group: g  u2.group:g   group:g  
            
            Session s = sf.getCurrentSession();
            s.beginTransaction();
            
            Group g = (Group) s.load(Group.class,1);
            //外键指向g的 user 都会被删掉。如果不想删,可以把User的group都设成null,不过这些数据也就成了垃圾数据。
            s.delete(g);
            s.getTransaction().commit();
        }
    }
  • 相关阅读:
    网络规划和布线
    网络编程
    NoSQL 非关系数据库
    OpenCV
    首页
    C++关键字
    TCP/IP 详解7 Ping指令
    TCP详解 (1)
    GRE封装解封装过程
    GRE tunnel
  • 原文地址:https://www.cnblogs.com/lihaoyang/p/4925916.html
Copyright © 2020-2023  润新知