首页 > 代码库 > Hibenate 课堂笔记

Hibenate 课堂笔记

1.jar文件导入项目中
2.添加Hibernate.cfg.xml文件
3.创建数据库表
4.创建该表对应的持久化类PO
5.添加映射文件xxx.hbm.xml
6.添加SessionFactory工厂类

 <!-- 一对多,并且子表列比较多,在程序中有对应的持久化类时   -->
        <set name="students">
            <!-- key指的是子表的外键列 -->
            <key column="GID"/>
            <!-- 指集合中的元素是哪个类型的对象 -->
            <one-to-many class="com.pb.Student"/>
        </set>
        <!-- 多对一 -->
        <many-to-one name="grade" class="com.pb.Grade">
            <!-- 指定外键列 -->
            <column name="GID"/>
        </many-to-one>
        
        <!-- 当使用外键实现一对一时: -->
        <!-- 一对一,主动方 -->
        <one-to-one name="paper" class="com.pb.Paper" cascade="all" lazy="false"/>
        <!-- 多对一 ,被动方-->
        <many-to-one name="student" class="com.pb.Student" unique="true" lazy="false">
            <column name="SID"/>
        </many-to-one>
        
        <!-- 多对多,通过中间表,不增加持久化类 -->
        <set name="courses" table="sc"><!-- table:中间表 -->
            <key column="sid"/><!-- 当前表和中间表之间的外键,为中间表的列 -->
            <!-- class:当前set中元素的类型。
                 column:中间表和课程表之间的外键,为中间表的列 -->
            <many-to-many class="com.pb.Course" column="cid"/>
        </set>
        
        
        
        
        
        <!-- 一对多,并且子表只有外键列和值列 -->
        <!-- name指集合属性名,table指集合数据是从哪个表来的 -->
        <set name="images" table="IMAGES">
            <!-- key指的是子表的外键列 -->
            <key column="userId"/>
            <!-- 指集合中的元素是从子表的哪个列取出来的 -->
            <element column="FILENAME" type="string"/>
        </set>
        <!-- 一对多,并且子表有三个列:外键、索引列、值列 -->
        <!-- name指的是集合属性名, table指集合数据是从哪个表来的 -->
        <list name="images" table="IMAGES">
            <!-- key指的是子表的外键列 -->
            <key column="userId"/>
            <!-- list-index指的是子表的索引列 -->
            <list-index column="POSITION"/>
            <!-- 指集合中的元素是从子表的哪个列取出来的:值列 -->
            <element column="FILENAME" type="string"/>
        </list>
        
         <!-- 一对多,并且子表有三个列:外键、键列、值列 -->
         <!-- name指的是集合属性名, table指集合数据是从哪个表来的 -->
         <map name="images" table="IMAGES">
            <!-- key指的是子表的外键列 -->
            <key column="userId"/>
            <!-- 指键列是字表的哪个列 -->
            <map-key column="IMAGE_NAME" type="string"/>
            <!-- 指集合中的元素是从子表的哪个列取出来的:值列 -->
            <element column="FILENAME" type="string"/>
        </map>
        






HQL: 查询属性和类名
1.创建Query对象
2.调用相应方法获得结果
   2.1.执行查询:
    list()查询一次,
    iterator()查询1+n次,
    uniqueResult()查询一条记录
   2.2.更新、删除
       executeUpdate()

1.查询所有列,不带条件
  from 类名
2.查询所有列,带条件
  2.1.拼接字符串
        String hql = "from 类名 where 属性1=‘"+变量+"‘
  2.2.使用问号占位符
        String hql = "from 类名 where 属性1=?"
  2.1.使用命名参数
        String hql = "from 类名 where 属性1=:参数名1"

3.查询某些列,不带条件
  select 属性1,...属性n from 类名
  查出的结果是List<Object[]>

4.查询一个列,不带条件
  select 属性1 from 类名
  查出的结果是List<Object>

5.查询某些列,不带条件,以对象封装
  select new 类名(属性1,...属性n) from 类名
  查出的结果是List<类名>


6.连接查询
  String hql="from 类名 join 当前类的连接属性"
   Student grade

7.检索策略
  7.1.类级别
      只对load方法起作用。
      Grade.hbm.xml里面的<class>标签添加属性lazy="true/false",默认是true
      表现:当执行load方法时,并不执行sql语句,而是创建一个只有oid值的代理对象;当访问该对象的非oid属性时,执行sql

  7.2.关联级别
      对所有查询方法都有效。
      Grade.hbm.xml里面的关联集合属性<set>中添加lazy="true/false",默认是true
       表现:当执行查询方法时,只执行对主表查询的sql语句;当访问该对象的关联集合属性时,执行对子表查询的sql语句


  7.3.批量检索
      Grade.hbm.xml里面的关联集合属性<set>中添加batch-size="2~10".在查询关联集合对象时批量查询,提交查询性能

  7.4.Fetch:通过什么查询语句查询关联集合对象
          select,subselect(都支持立即检索或延迟检索),
          join(立即检索):1.只支持立即检索,忽略lazy属性;2.不支持hql查询,只支持get和load

Criteria标准查询
   Criteria ct = session.createCriteria(Grade.class);
   ct.add(Restrictions.eq("gid",1001));
   ct.add(Restrictions.or(
        Restrictions.eq("age",20),
        Restrictions.like("username","%马%")
   ));
   ct.add(Restrictions.between("gid",1001,1003));
   ct.add(Restrictions.in("gid",new Integer[]{1001,1002,1003}));
   ct.addOrder(Order.desc("gid"));//降序排列,Order.asc()升序
   
   //示例查询:条件较多,且都是等值判断时,可以使用示例查询(条件中没有主键)
   Grade grade = new Grade();
   grade.setName("计算机一班");
   grade.setDesc("计算机科学与应用一班");
   ct.add(Example.create(grade));

   //分组聚合
   ct.setProjection(Projections.rowCount());
   ct.setProjection(Projections.groupProperty("gdesc"))

   List<Grade> list = ct.list();

startDate,endDate
统计某个工人4月的班次
where startDate>=‘2014-4-1‘ and startDate<‘2014-5-1‘


统计某工人4月出现的所有班次
where endDate>=‘2014-4-1‘ and startDate<‘2014-5-1‘


命名HQL查询
1.在映射文件中添加query
  <query name="loginUser">
     <![CDATA[
           from Login lo where lo.username=:username and lo.password=:password
     ]]>      
  </query>

2.代码中使用命名HQL查询
  Query query = session.getNamedQuery("loginUser");
  Login login = new Login();//创建查询模板
  login.setUsername("马达");
  login.setPassword("111111");
  query.setProperties(login);
  List<Login> list = query.list();

本地SQL查询
  String sql = "select {l.*} from login l where l.username=‘马达‘";
  SQLQuery query = session.createSQLQuery(sql).setEntity("l",Login.class);
  List list = query.list();




命名SQL查询
1.在映射文件中添加sql-query
  <sql-query name="findUser">
     <![CDATA[
           select {l.*} from Login l where l.username=?
     ]]>
     <return alias="l" class="com.pb.Login"/>
  </sql-query>

2.代码中使用命名SQL查询
  Query query = session.getNamedQuery("findUser");
  query.setString(0,"马达");
  List<Login> list = query.list();




批量插入数据
  1.在Hibernate.cfg.xml文件中,设置batch-size, use-second-level-cache;
  2.在执行批量插入的循环中,添加判断,每二十个清空一次缓存,session.flush(),session.clear()

批量更新数据:
ScrollableResults result = session
                .createQuery("from Login")
                .scroll(ScrollMode.FORWARD_ONLY);
        int count=0;
        while(result.next()){
            Login login = (Login)result.get(0);
            login.setAge(21);
            if(count%20==0){
                session.flush();//强制数据库和持久状态的对象同步
                session.clear();
            }
            count++;
        }
        tr.commit();
        session.close();


执行存储过程:
  CallableStatement call = session.connection().prepareCall("{call   login_insert(?,?,?)}");
  call.setString(1,"张三");
  call.setString(2,"男");
  call.setLong(3,21);
  //执行增删改的存储过程
  call.executeUpdate();
  tr.commit();
  session.close();

  执行查询的存储过程
  CallableStatement call = session.connection()
        .prepareCall("{call login_query(?)}");
  call.registerOutParameter(1, OracleTypes.CURSOR);
  call.execute();
  ResultSet rs = (ResultSet)call.getObject(1);
  ...
 

执行命名存储过程sql
     <sql-query name="findUser" callable="true">
        {call loginGetAll(?)}        
        <return alias="l" class="com.pb.Login"/>
     </sql-query>




使用注解配置Hibernate映射
1.不需要配置映射文件
2.可以自动创建表
3.<mapping class="com.pb.Login"/>
4.创建sessionFactory时,使用的是AnnotationConfiguration
5.要添加三个jar包:
    commons-logging-1.0.4.jar
    hibernate-annotations.jar
    hibernate-commons-annotations.jar


@Entity
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Basic

命名hql查询
@NamedQuery(name="命名hql查询",query="from Login")

命名本地查询
@NamedNativeQuery(
        name="命名本地查询",
        query="select * from login",
        resultSetMapping="结果集映射名"
)
@SqlResultSetMapping(name="结果集映射名",entities={
        @EntityResult(entityClass=Login.class,fields={
            @FieldResult(name="id",column="ID")
        })
})



Hibernate注解配置主外键关系
 1.一对一
丈夫类/Husband:
 @OneToOne(cascade=CascadeType.ALL)
 @PrimaryKeyJoinColumn//这个注解只能写在主(生成ID)的一端
 private Wife wife;

妻子类/Wife:
 @OneToOne(cascade=CascadeType.ALL,mappedBy="wife")
 private Husband husband;

2.一对多(多对一)
读者类/Reader:
 @OneToMany(mappedBy="reader",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
 private Set<Book> books = new HashSet<Book>();

图书类/Book:
 @ManyToOne(cascade=CascadeType.ALL,optional=false)
 @JoinColumn(name="read_id",referencedColumnName="id")//外键为read_id,与Reader中的id关联
 private Reader reader;

3.多对多
    学生对课程:
学生类/Student:
@ManyToMany(targetEntity=com.hibernate.many2many.Course.class,   cascade={CascadeType.MERGE,CascadeType.PERSIST})   
@JoinTable(name="student_course",//中间表
  joinColumns={@JoinColumn(name="student_id")},//中间表中对应学生表的外键
  inverseJoinColumns={@JoinColumn(name="course_id")}//中间表中对应课程表的外键
)   
private Set<Course> course;   

课程类/Course:
@ManyToMany(targetEntity=com.hibernate.many2many.Student.class,   
   cascade={CascadeType.MERGE,CascadeType.PERSIST})   
@JoinTable(name="student_course",              //中间表
   joinColumns={@JoinColumn(name="course_id")},//中间表中对应课程表的外键
   inverseJoinColumns={@JoinColumn(name="student_id")}//中间表中对应学生表的外键
)   
private Set<Student> student;  

Hibenate 课堂笔记