Java框架之Hibernate(二)

本文主要介绍:

1 Criteria 接口

2 用 myeclipse 反向生成

3 hibernate  主键生成策略

4 多对一

5 一对多

6 使用List 集合的一对多

7 多对多

一、Criteria 接口

//例一
            public static AdminInfo getLoginAdminCriteria(String adminName,String password){
                try{
                    Session s=HibUtil.getSession();
                    Criteria c=s.createCriteria(AdminInfo.class);
                    c.add(Restrictions.eq("adminName", adminName));
                    c.add(Restrictions.eq("password", password));
                    
                    return (AdminInfo) c.uniqueResult();
        
                }finally{
                    HibUtil.closeSession();
                }
            }

QBC常用限定方法

Restrictions.eq --> equal,等于.

Restrictions.allEq --> 参数为Map对象,使用key/value进行多个等于的比对,相当于多个Restrictions.eq的效果

Restrictions.gt --> great-than > 大于

Restrictions.ge --> great-equal >= 大于等于

Restrictions.lt --> less-than, < 小于

Restrictions.le --> less-equal <= 小于等于

Restrictions.between --> 对应SQL的between子句

Restrictions.like --> 对应SQL的LIKE子句

Restrictions.in --> 对应SQL的in子句

Restrictions.and --> and 关系

Restrictions.or --> or 关系

Restrictions.isNull --> 判断属性是否为空,为空则返回true

Restrictions.isNotNull --> 与isNull相反

Restrictions.sqlRestriction --> SQL限定的查询

Order.asc --> 根据传入的字段进行升序排序

Order.desc --> 根据传入的字段进行降序排序

MatchMode.EXACT --> 字符串精确匹配.相当于"like 'value'"

MatchMode.ANYWHERE --> 字符串在中间匹配.相当于"like '%value%'"

MatchMode.START --> 字符串在最前面的位置.相当于"like 'value%'"

MatchMode.END --> 字符串在最后面的位置.相当于"like '%value'"

//例子  
         Criteria c=s.createCriteria(AdminInfo.class);
            
        // 查询 id在 10 到 30 之间的用户
          c.add(Restrictions.between("id",10,30)).list();
          
         //查询 adminName 在 张三,李四,王五之间的 
          String [] names={"张三","李四","王五"};  //这里也可以用集合 只要是从Collection派生的都可以
          c.add(Restrictions.in("userName",names)).list();
          
         //查询 note为空的用户
          c.add(Restrictions.isNull("note")).list();
          
         //查询年龄为空,或名字为admin的  
          c.add(Restrictions.or(Restrictions.eq("adminName", "admin"),Restrictions.isNull("age")));
 //使用 QBC实现动态查询(以前的例子)
         public List<AdminInfo> getAdminList(String adminName,String password,String note) {
                 String sql="select * from adminInfo where 1=1 ";
                 if(adminName!=null){
                         sql+=" and adminName='"+addminName+"'";
                 }
                 if(password!=null){
                         sql+=" and adminName='"+password+"'";
                 }
                 if(note!=null){
                         sql+=" and adminName='"+note+"'";
                 }
       }
 //上例使用 QBC
           public static List<AdminInfo> getLoginAdminList(String adminName,String password,String note){
                try {
                    Session s=HibUtil.getSession();
                    Criteria c=s.createCriteria(AdminInfo.class);
                    
                    if(adminName!=null){
                        c.add(Restrictions.eq("adminName", adminName));
                    }
                    
                    if(password!=null){
                        c.add(Restrictions.eq("password", password));
                    }
                    
                    if(note!=null){
                        c.add(Restrictions.eq("note", note));
                    }
                    
                    return c.list();
                    
                }finally{
                    HibUtil.closeSession();
                }
            }
                 
            //官方推荐使用HQL

二、用 myeclipse 反向生成 

Hibernate 的开发流程

1) 由domain对象开始   bean  -> 生成xml -> 生成数据库表

2) 由数据库表开始, 由表生成 bean 和 配置文件

3) 由配置文件开始

关于 <property name="hbm2ddl.auto">update</property> 这个配置

#Hibernate.hbm2ddl.auto create-drop   //创建,用完之后再删除

#Hibernate.hbm2ddl.auto create  //这个操作会重新创建表

#Hibernate.hbm2ddl.auto update  //会把对象模型的变化,表现在关系模型上

#Hibernate.hbm2ddl.auto validate  //当对象模型和关系模不一样的时候,会发生错误(通常生产环境下用)

、Hibernate  主键生成策略

所有的主键生成器都实现了  org.Hibernate.id.IdentifierGenerator  接口

常用的主键生成器

1) increament: 适合所有的数据库, 由hiberante来维护主键的生成(先查询最大的,再加1), 有线程安全问题,不适合多个进程的情况。用于 long ,short ,int ,生成的是数字型的自增的唯一标识,在集群的情况下不要用实测,在mysql下,无论原来是否设置了自增主键,用它都可以

2) identity:  适合于mysql , mssqlserver 等支持自增主键的数据库,主键不由 Hibernate 来维护,类型是 int, short,long。oracle中不能用 (无法将 NULL 插入 ("SA"."USERINFO"."ID") 这样的异常)

3) sequence: (顺列) 适合于oracle等支持序列的数据库, 主键值不由Hibernate维护。mysql不支持(出现 Dialect does not support sequences 这样的异常), 在 oracle中直接这样写:  <generator class="sequence" /> 它会对所有的表使用同一个序列。

4) native:  和底层数据库的具体特性有关, 如果是mysql或 mssqlserver ,它就会选择 identity, 如果是oracle 它会选  sequence

5) hilo: 高低位 根据 hilo算法 生成主键,支持所有的数据库, 需要一张额外的表生成的表名 默认是 Hibernate_unique_key 里面就一列 next_hi

<id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="hilo" >
                <param name="table">t_key</param>
                <param name="column">f_nextval</param>
                <param name="max_lo">100</param>
            </generator>
        </id>

6) uuid :  Hibernate 来维护的主键 ,支持所有数据库

 <id name="id" >
     <column name="id" />
     <generator class="uuid" />
</id>

//附 用java程序生成uuid => UUID.randomUUID().toString() c6204dc1-b9b6-40a9-a03a-a35ab6e6adc

 7) assigned : 主键由用户来维护, 如果选择了这种生成方式,则Hibernate不再帮我们生成主键,主键要由用户。在程序中指定,不指定将出错  ids for this class must be manually assigned before calling save():

四、多对一

//对象模型 
      //尼姑
      public class NiGu {
                    private int id;
                    private String fahao;
                    
                    private NiGuAn niguan; // 用的是NiGuAn 对象 这样就建立起了一对多的关联
                }
                
    //尼姑庵
    public class NiGuAn {
                    private int id;
                    private String name;
                }
//映射文件 (NiGuAn.hbm.xml)
            <Hibernate-mapping>
                <class name="cat.beans.NiGuAn" >
                    <id name="id">
                        <column name="id" />
                        <generator class="native" />   
                    </id>
                    <property name="name" />
                </class>
            </Hibernate-mapping>
            
            NiGu.hbm.xml
             <Hibernate-mapping>
            <class name="cat.beans.NiGu" >
                <id name="id">
                    <column name="id" />
                    <generator class="native" />   
                </id>
                <property name="fahao" />
                <many-to-one name="niguan" column="niguan_id"  />    //让它生成的外键这列的名字叫  niguan_id
                </class>
            </Hibernate-mapping>
//添加的方法
          public static void add(){
                    try{
                            NiGuAn niguan= new NiGuAn();
                            niguan.setName("普渡寺");
                            
                            NiGu nigu=new NiGu();
                            nigu.setFahao("灭绝师太");
                            
                            //建立起两对象模型的关联
                            nigu.setNiguan(niguan);
                            
                            Session s=HibUtil.getSession();
                            Transaction tx=s.beginTransaction();
                            
                            s.save(niguan);  //先存的是尼姑庵
                            s.save(nigu);
                            
                            tx.commit();
                                    
                        }
                        finally{
                            HibUtil.closeSession();
                        }    
                }

总结::

1) 只要对象模型建好了,生成关系模型(数据库表)的时候,也能正确的生成

2) 如果把上面的

s.save(niguan); 反过来写,会多生成一条sql语句,用来维护关联关系

s.save(nigu);

3) 如果不     s.save(niguan); 将出现下面的异常信息

object references an unsaved transient instance - save the transient instance before flushing: cat.beans.NiGuAn

对象引用了一个没有保存的瞬时对象

//查询 
          
          public static void main(String[] args) {
                    NiGu nigu=searchNiGu();
                    System.out.println(nigu.getFahao()); //可以输出结果
                    
                    /* 被关联的对象,查询的时候默认是使用懒加载的  如果下面的代码中没有
                       Hibernate.initialize(nigu.getNiguan()); 这句,将引发 
                        could not initialize proxy - no Session  */
                      System.out.println(nigu.getNiguan().getName()); 
                }
            
                //关于查询的例二
                public static NiGu searchNiGu(){
                    try{
                        Session s=HibUtil.getSession();
                        NiGu nigu= (NiGu) s.get(NiGu.class,1 );
                        Hibernate.initialize(nigu.getNiguan()); //通知Hibernate 直接把关联的数据查询出来
                        return nigu;
                    }finally{
                        HibUtil.closeSession();
                    }
                }
                
                //关于查询的例一
                public static void search(){
                    try{
                        Session s=HibUtil.getSession();
                        NiGu nigu= (NiGu) s.get(NiGu.class,1 );
                        
                        System.out.println(nigu.getFahao());
                        System.out.println(nigu.getNiguan().getName());  //能否把关联的数据查出来 ?
                        
                    }finally{
                        HibUtil.closeSession();
                    }
                }

五、一对多

//对象模型
//尼姑庵
public class NiGuAn {
                private int id;
                private String name;
                
                private Set<NiGu>niguList;  //一对多关联
            }
//映射文件(NiGuAn.hbm.xml)
            <Hibernate-mapping>
                <class name="cat.beans.NiGuAn" >
                    <id name="id">
                        <column name="id" />
                        <generator class="native" />   
                    </id>
                    <property name="name" />
                    
                    <set name="niguList">
                        <key column="niguan_id" />
                        <one-to-many class="NiGu" />
                    </set>   
                </class>
            </Hibernate-mapping>
//映射文件 (NiGuAn.hbm.xml)
            <Hibernate-mapping>
                <class name="cat.beans.NiGuAn" >
                    <id name="id">
                        <column name="id" />
                        <generator class="native" />   
                    </id>
                    <property name="name" />
                </class>
            </Hibernate-mapping>
            
            NiGu.hbm.xml
             <Hibernate-mapping>
            <class name="cat.beans.NiGu" >
                <id name="id">
                    <column name="id" />
                    <generator class="native" />   
                </id>
                <property name="fahao" />
                <many-to-one name="niguan" column="niguan_id"  />    //让它生成的外键这列的名字叫  niguan_id
                </class>
            </Hibernate-mapping>
//添加的方法              
            public static  void add(){
                    NiGuAn niguan=new NiGuAn();
                    niguan.setName("少林寺");
                    
                    NiGu nigu1=new NiGu();
                    nigu1.setNiguan(niguan);
                    nigu1.setFahao("空闻");
                    
                    NiGu nigu2=new NiGu();
                    nigu2.setNiguan(niguan);
                    nigu2.setFahao("玄苦");
                    
                    try{
                        Session s=HibUtil.getSession();
                        Transaction tx=s.beginTransaction();
                        
                        /*
                        Set<NiGu> niguList=new HashSet<NiGu>();
                        niguList.add(nigu1);
                        niguList.add(nigu2);
                        
                        niguan.setNiguList(niguList);  */
            
                        s.save(niguan);
                        s.save(nigu1);
                        s.save(nigu2);
                        
                        tx.commit();
                        
                    }finally{
                        HibUtil.closeSession();
                    }
                          

                public static void main(String[] args) {
                    // add(); 
                    NiGuAn niguan= search2();
                    System.out.println(niguan.getName());
                    for(NiGu n:niguan.getNiguList()){
                        System.out.println(n.getFahao());
                    }
                }
                
                public static NiGuAn  search2(){
                    try{
                        Session s=HibUtil.getSession();
                        NiGuAn  niguan= (NiGuAn) s.get(NiGuAn.class, 4);
                        Hibernate.initialize(niguan.getNiguList());
                        return niguan;
                        
                    }finally{
                        HibUtil.closeSession();
                    }
                }
                
                
                public static void search(){
                    try{
                        Session s=HibUtil.getSession();
                        NiGuAn niguan =(NiGuAn) s.get(NiGuAn.class, 4);
                        
                        System.out.println(niguan.getName());
                        Set<NiGu> niguList= niguan.getNiguList();
                        for (NiGu n:niguList) {
                            System.out.println(n.getFahao());
                        }
                    
                    }finally{
                        HibUtil.closeSession();
                    }
                }

六、使用List 集合的一对多

对象模型中的set 要换成list

 <!-- 把它换成下面的配置即可
        <set name="niguList">
            <key column="niguan_id" />
            <one-to-many class="NiGu" />
        </set>   
        -->
        
        <list name="niguList">
            <key column="niguan_id" />
            <index column="indexNo" />
            <one-to-many class="NiGu" />
        </list>
//如果对象模型还是使用list,但关系模型中不要排序列,可以用bag 来配置
<bag name="niguList">
     <key column="niguan_id" />
     <one-to-many class="NiGu" />
</bag> 
 //添加方法  
                public static  void add(){
                        NiGuAn niguan=new NiGuAn();
                        niguan.setName("九峰寺");
                        
                        NiGu nigu1=new NiGu();
                        nigu1.setNiguan(niguan);
                        nigu1.setFahao("空空大师");
                        
                        NiGu nigu2=new NiGu();
                        nigu2.setNiguan(niguan);
                        nigu2.setFahao("玄玄");
                        
                        NiGu nigu3=new NiGu();
                        nigu3.setNiguan(niguan);
                        nigu3.setFahao("灭绝");
                        
                        try{
                            Session s=HibUtil.getSession();
                            Transaction tx=s.beginTransaction();
                            
                            
                            List<NiGu> niguList=new ArrayList<NiGu>();
                            niguList.add(nigu1);
                            niguList.add(nigu2);
                            niguList.add(nigu3);
                            
                            niguan.setNiguList(niguList);  
    
                            s.save(niguan);
                            s.save(nigu1);
                            s.save(nigu2);
                            s.save(nigu3);
                    
                            tx.commit();
                            
                            //说明
                             /*
                             List<NiGu> nlist=niguan.getNiguList();  没有问题
                             ArrayList<NiGu> nlist=(ArrayList<NiGu> )niguan.getNiguList(); 
                             将出现异常 ClassCastException: org.Hibernate.collection.PersistentBag cannot be cast to java.util.ArrayList        
                             
                             */

                        
                        }finally{
                            HibUtil.closeSession()

七、多对多

//对象模型 
public class Student {
            private int id;
            private String stuName;
            private Set<Teacher> teacherList;
            
        }
        
public class Teacher {
            private int id;
            private String teacherName;
            private Set<Student> stuList;  //建立关联
        }
//Teacher.hbm.xml    
        <Hibernate-mapping package="cat.beans">
            <class name="Teacher" >
                <id name="id">
                    <column name="id" />
                    <generator class="native" />   
                </id>
                <property name="teacherName" />
                <set name="stuList" table= "teacher_student"  lazy="false">  //指明不要懒加载
                    <key column="teacher_id" /> <!-- 将来根据 teacher_id列表中间表找学生 -->
                    <many-to-many class="Student" column="stucent_id" />
                </set>   
            </class>
        </Hibernate-mapping>
//Student.hbm.xml 
   <Hibernate-mapping package="cat.beans">
    <class name="Student" >
        <id name="id">
            <column name="id" />
            <generator class="native" />   
        </id>
        <property name="stuName" />
        <set name="teacherList" table= "teacher_student">
            <key column="student_id" /> 
            <many-to-many class="Teacher" column="teacher_id" />
        </set>   
    </class>
  </Hibernate-mapping>
//测试
       public static void main(String[] args) {
                Teacher t=search();
                
                System.out.println(t.getTeacherName());
                
                for(Student stu:t.getStuList()){
                    System.out.println(stu.getStuName());
                }
            }
            
            public static Teacher search(){
                return (Teacher) HibUtil.get(Teacher.class, 1);
            }
        
            public static void add(){
                //老师的数据
                Teacher t1=new Teacher();
                t1.setTeacherName("成秀秀");
                
                Teacher t2=new Teacher();
                t2.setTeacherName("史老师");
                
                Set<Teacher> teacherList=new HashSet<Teacher>();
                teacherList.add(t1);
                teacherList.add(t2);
                
                //学生的数据
                Student stu1=new Student();
                stu1.setStuName("刘冰");
                
                Student stu2=new Student();
                stu2.setStuName("侯晨阳");
                
                Set<Student> studentList=new HashSet<Student>();
                
                studentList.add(stu1);
                studentList.add(stu2);
                
                t1.setStuList(studentList); //建立起老师和学生的关联
                t2.setStuList(studentList); 
                
                ///////有没有必要//////
                //stu1.setTeacherList(teacherList);
                //stu2.setTeacherList(teacherList);
                //////////////////////
                
                Session s=HibUtil.getSession();
                Transaction tx=s.beginTransaction();
                
                s.save(t1);
                s.save(t2);
                s.save(stu1);
                s.save(stu2);
                
                tx.commit();
            
                s.close();
            
            }

高低位: 附:它的算法

next_hi * (max_lo + 1) + lo

1. 读取并记录数据库的Hibernate_unique_key表中next_hi字段的值,数据库中此字段值加1 并保存

2. nHibernate取得lo值(从0循环到(max_lo-1),到max_lo的时候,再执行步骤1,然后 lo继续从 0循环到(max_lo-1))

3. 最后根据公式计算主键值。

注意:

所谓的hilo性能比identity好的前提是在同一Session里批量添加记录的时候(id不用每添加一条记录都从数据库里返回);

如果两条记录在不同的Session添加,那么每条记录的id值会相隔32767的差值(max_lo默认值是 32767时)。                

由于我们多数都是一条一条记录的添加的,这样如果按 max_lo的默认值32767来生成主键的话,其值很快就会暴增,甚至会出现溢出的可能。

posted @ 2018-01-05 16:13  江河湖泊  阅读(380)  评论(0编辑  收藏  举报