• Hibernate ORM框架——综合


    换一个连接数据mySql数据库的项目:HibernateStudy_cascade_inverse_query
    **********1.支持sql server需要的设置*******************************************************
        a):驱动jar的处理-->导入sqljdbc42.jar连接数据库驱动
        b):修改hibernate.cfg.xml中配置相关的连接,方言
            <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
            <property name="connection.url">jdbc:sqlserver://localhost:1433;databaseName=demo</property>
            <property name="connection.username">sa</property>
            <property name="connection.password"></property>
            <property name="dialect">org.hibernate.dialect.SQLServer2008Dialect</property>
        c):开启TCP/IP的支持-->计算机管理,服务和应用程序,SQL Server配置管理器,SQL Native Cloient 10.0配置,客户端协议 
        d):启动sql server的服务
        
    **********2.关联数据的处理****************************************************************
    关联数据的插入,更新(修改),删除的顺序
        假定A是主表,B是子表
        create table A
        (
            aid varchar2(255 char) not null,
            primary key(aid)
        )
        create table B
        (
            bid varchar2(255 char) not null,
            primary key(bid),
            raid foreign key(aid) references A   //外键
        )
    
    在MySQL数据库层面***************************************
        a)insert(添加操作) :
            先主表,后从(子)表
        b)update(更新)(我们一般是不更新表的主键)
            在数据库层面来看,如果不考虑更新主键,顺序是无关紧要的。
        c)delete(删除)
            先删从表(子表)的,然后再删主表
    
    
    在hibernate代码层面*************************************
    关联数据如果MySQL的代码和自己预想中的有出入,如何处理,需考虑的点。
        1.考虑调用session对象的save,update,delete的顺序问题
        2.考虑在代码层面有没有设置关系,外键是否允许为null
        3.考虑对象此时的状态
        帮助判断工具:sql server的监听器
    
    
    **********3.cascade(级联)*************************************************************
    
     
    **********4.inverse(确定关系维护方)******************************************************
    关系维护,本质就是谁负责处理外键列的值。
    
    inserse 一般是出现的映射文件的set元素里面
    
    因为出现在set里面,也就是出现主表的映射文件中
    
    如果把inserse设置为true,就表示由对方,也就是
    子表来维护关系(就不会继续进行修改操作,[而此时查表时的外键值也为空]),主的一方不管。
    -->在添加子表的时候,相关联的主表就跟着添加了
    
    一般默认inserse的值为false,即为自己就是维护关系方,会进行修改(更新)操作
    
    所以一般来说永远交给子表来维护关系,是比较合理的(比如:一个应届生,他并不属于任何部门,
    那么在这个应届生中存在两张表,一张是个人的信息表,一张是部门表。在个人信息表中的所属部门可以为空,
    等到该应届生,正式成为某某部门的时候,才不为空。也同时说明,外键一般时可以为空的)
    
    
    **********5.关联数据的查询形式(检索策略)****************************************************
    关联数据的加载,有3种情况
    1.延迟(lazy)也叫作懒加载:
        当只在查找班级数据后,马上调用session.close();那么久默认为延迟(lazy)加载。即后面还没有查找完的语句就不查找了
        默认:lazy="true"
        
    2.勤加载(eager)
        当只在查找班级数据后,马上调用session.close();而后面还没有查找完的语句就系统仍然自动查找,称为勤加载(eager)
        lazy="false"如在学生这边加,在查询学生信息的同时也查询班级信息是正常的
        
    3.外键加载(显式加载):
        outer-join="true":查询的SQL语句中只用左外连接显示出一条查询结果
        避免普通查询,两张表,则需要发送两条select语句。

    补充:3.级联cascade

    (1)class类映射文件

    <?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="shuang.m2oo2m">
        <class name="ClassInfo" table="CLASSINFO">
            <id name="cid" column="cid">
                <generator class="assigned"></generator>
            </id>
            <property name="name"></property>
            
            <set name="persons" cascade="all">
                <key column="rci"></key>
                <one-to-many class="Person"/>
            </set>
        </class>
    </hibernate-mapping>

    (2.1)Main测试,级联添加

    private static void cascadeInsert() {
            SessionFactory sf = HibernateUtil.getSessionFactory();
            Session s = sf.openSession();
            Transaction tx = s.beginTransaction();
            
            ClassInfo ci = new ClassInfo();
            ci.setCid("c1111");
            ci.setName("banji1");
            
            Set<Person> set = new HashSet<Person>();
            
            Person p = new Person();
            p.setPid("p111");
            p.setName("ren1");
            //p.setCi(ci);可以不需要,
            set.add(p);
            
            ci.setPersons(set);//此处已经说明了它俩关联了
            
            s.save(ci);
            //只把ci的数据持久化(save),不save人。并且在ClassInfo_m2oo2m.xml里写cascade="all"
            //班级和人的数据均正常添加
            
            tx.commit();
            s.close();
            sf.close();
            
            
            //运行结果为:先查询这个班级有没有人,然后再添加班级,添加人
            /*create table CLASSINFO (
               cid varchar(255) not null,
                name varchar(255),
                primary key (cid)
            )
            
            create table persons (
               pid varchar(255) not null,
                name varchar(255),
                rci varchar(255),
                primary key (pid)
            )
            
            alter table persons 
               add constraint FK7q2p61lu2253rtputmlhokd1e 
               foreign key (rci) 
               references CLASSINFO
               
               
               
            -----------------重点-----------------------   
            select
                person_.pid,
                person_.name as name2_1_,
                person_.rci as rci3_1_ 
            from
                persons person_ 
            where
                person_.pid=?
            insert 
            into
                CLASSINFO
                (name, cid) 
            values
                (?, ?)
            insert 
            into
                persons
                (name, rci, pid) 
            values
                (?, ?, ?)
            update
                persons 
            set
                rci=? 
            where
                pid=?*/        
    
            
            
            
            //反之,如果不使用级联(在ClassInfo_m2oo2m.xml里写cascade="all")
            //则数据在直接添加时并不会去找是存在临时的人的数据,
            //但是又因为人和班级有关联,会报错
            /*Hibernate: 
                insert 
                into
                    CLASSINFO
                    (name, cid) 
                values
                    (?, ?)
            Hibernate: 
                update
                    persons 
                set
                    rci=? 
                where
                    pid=?*/
        }

    (2.2)Main测试,级联删除

    private static void cascadeDelete() {
            SessionFactory sf = HibernateUtil.getSessionFactory();
            Session s = sf.openSession();
            Transaction tx = s.beginTransaction();
            
            ClassInfo ci = s.get(ClassInfo.class, "c1111");
            s.delete(ci);
            /*不使用级联的普通删除结果(不在ClassInfo_m2oo2m.xml里写cascade="all"):
             * 先根据id查到所删除的数据,然后再修改所关联的人的班级信息为null。
             * 最后删除该行
             * Hibernate: 
                select
                    classinfo0_.cid as cid1_0_0_,
                    classinfo0_.name as name2_0_0_ 
                from
                    CLASSINFO classinfo0_ 
                where
                    classinfo0_.cid=?
                Hibernate: 
                    update
                        persons 
                    set
                        rci=null 
                    where
                        rci=?
                Hibernate: 
                    delete 
                    from
                        CLASSINFO 
                    where
                        cid=?*/
            
            
            /*使用级联的普通删除结果(在ClassInfo_m2oo2m.xml里写cascade="all"):
             * 班级和所关联的人的数据都一同删掉
             * Hibernate: 
                    select
                        classinfo0_.cid as cid1_0_0_,
                        classinfo0_.name as name2_0_0_ 
                    from
                        CLASSINFO classinfo0_ 
                    where
                        classinfo0_.cid=?
                Hibernate: 
                    select
                        persons0_.rci as rci3_1_0_,
                        persons0_.pid as pid1_1_0_,
                        persons0_.pid as pid1_1_1_,
                        persons0_.name as name2_1_1_,
                        persons0_.rci as rci3_1_1_ 
                    from
                        persons persons0_ 
                    where
                        persons0_.rci=?
                Hibernate: 
                    update
                        persons 
                    set
                        rci=null 
                    where
                        rci=?
                Hibernate: 
                    delete 
                    from
                        persons 
                    where
                        pid=?
                Hibernate: 
                    delete 
                    from
                        persons 
                    where
                        pid=?
                Hibernate: 
                    delete 
                    from
                        CLASSINFO 
                    where
                        cid=?
             * */
            
            tx.commit();
            s.close();
            sf.close();
            
            
        }

    补充:4.inverse(确定关系维护方)
    Main测试
    private static void testInverse() {
            SessionFactory sf = HibernateUtil.getSessionFactory();
            Session s = sf.openSession();
            Transaction tx = s.beginTransaction();
            
            ClassInfo ci = new ClassInfo();
            ci.setCid("c1111");
            ci.setName("banji1");
            
            Set<Person> set = new HashSet<Person>();
            
            Person p = new Person();
            p.setPid("p111");
            p.setName("ren1");
            p.setCi(ci);
            set.add(p);
            
            ci.setPersons(set);
            p.setCi(ci);
            
            s.save(ci);
            s.save(p);
            
            tx.commit();
            s.close();
            sf.close();
        }


    补充:5.关联数据的查询形式(检索策略)
    (5.1)班级的映射文件
    <?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="shuang.m2oo2m">
        <class name="ClassInfo" table="CLASSINFO">
            <id name="cid" column="cid">
                <generator class="assigned"></generator>
            </id>
            <property name="name"></property>
            
            <set name="persons" lazy="true">
                <key column="rci"></key>
                <one-to-many class="Person"/>
            </set>
        </class>
    </hibernate-mapping>

    (5.2)Main测试代码(是否为勤加载或者懒加载)
    private static void LazyFlag() {
            SessionFactory sf = HibernateUtil.getSessionFactory();
            Session s = sf.openSession();
            Transaction tx = s.beginTransaction();
            
            ClassInfo ci = s.get(ClassInfo.class, "c1111");
            System.out.println(ci.getName());
            
            tx.commit();
            s.close();
            
            Set<Person> persons = ci.getPersons();
            for(Person p : persons){
                System.out.println(p.getName());
            }
            
            s.close();
            sf.close();
    
            /*不写,默认懒加载==班级的映射文件中,默认:lazy="true"
             * 当只在查找班级数据后,马上调用session.close();那么久默认为延迟(lazy)加载。即后面还没有查找完的语句就不查找了
             * Hibernate: 
                    select
                        classinfo0_.cid as cid1_0_0_,
                        classinfo0_.name as name2_0_0_ 
                    from
                        CLASSINFO classinfo0_ 
                    where
                        classinfo0_.cid=?
                banji1
             * */
            
            /*反之:如果班级的映射文件中,设置关键词lazy="false":即为勤加载
             * 当只在查找班级数据后,马上调用session.close();而后面还没有查找完的语句就系统仍然自动查找,称为勤加载(eager)
             * */
            
            //注意:一般班级中默认是懒加载,人中默认是勤加载,是正常的
        }

    (5.3)外键加载(显式加载)

    班级映射文件:

    <?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="shuang.m2oo2m">
        <class name="ClassInfo" table="CLASSINFO">
            <id name="cid" column="cid">
                <generator class="assigned"></generator>
            </id>
            <property name="name"></property>
            
            <set name="persons" outer-join="true">
                <key column="rci"></key>
                <one-to-many class="Person"/>
            </set>
        </class>
    </hibernate-mapping>

    Main测试:

    private static void showLoad() {
            SessionFactory sf = HibernateUtil.getSessionFactory();
            Session s = sf.openSession();
            Transaction tx = s.beginTransaction();
            
            ClassInfo ci = s.get(ClassInfo.class, "c1111");
            System.out.println(ci.getName());
            
            tx.commit();
            s.close();
            sf.close();
            
            /*在班级映射文件中使用关键词outer-join="true"的查询结果:
             * 会在查询班级的同时,把相关联表的一起查询
             * Hibernate: 
                    select
                        classinfo0_.cid as cid1_0_0_,
                        classinfo0_.name as name2_0_0_,
                        persons1_.rci as rci3_1_1_,
                        persons1_.pid as pid1_1_1_,
                        persons1_.pid as pid1_1_2_,
                        persons1_.name as name2_1_2_,
                        persons1_.rci as rci3_1_2_ 
                    from
                        CLASSINFO classinfo0_ 
                    left outer join
                        persons persons1_ 
                            on classinfo0_.cid=persons1_.rci 
                    where
                        classinfo0_.cid=?
                banji1
             * */
            
            
            
            /*不使用的结果:只会查询他自己的
             * Hibernate: 
                    select
                        classinfo0_.cid as cid1_0_0_,
                        classinfo0_.name as name2_0_0_ 
                    from
                        CLASSINFO classinfo0_ 
                    where
                        classinfo0_.cid=?
                banji1
             * 
             * */
            
            //好处:避免普通查询,两张表,则需要发送两条select语句。
        }


    /*以上个人整理笔记,如果有误或者有不懂的地方,欢迎评论与指出*/

  • 相关阅读:
    redolog switch会发生完全检查点还是增量检查点?
    4G牌照发放生变 专家谏言电信联通如何选择
    [财富]iPhone如何征服日本?
    审计中移动现多处问题或致地方高层落马
    诺基亚CEO:Lumia不会像安卓推廉价版机型
    菜鸟学JDBC(二)
    简易网页采集器的实现
    手Q与微信:最终结局将会是手足相残!
    做网站Http状态码详解
    PHP $_SERVER['HTTP_REFERER'] 获取前一页面的 URL 地址
  • 原文地址:https://www.cnblogs.com/Sunny-lby/p/7384671.html
Copyright © 2020-2023  润新知