框架之Hibernate(二)

来源:互联网 发布:淘宝开店做代理 编辑:程序博客网 时间:2024/06/11 18:48
一.一对多的关系映射
    1.配置文件中的配置:
  1. <set name="linkmans" table="cst_linkman">
  2. <key column="lkm_cust_id"></key>
  3. <one-to-many class="CstLinkMan"/>
  4. </set>
    2.元素
        *set元素: 作用:用于映射集合属性
                    属性:name:指定集合属性的名称       table:指定集合中元素对应的表
        *key元素:作用:用于映射外键的,一般只出现在set元素的内部
                    属性:column:指定表中外键字段的名称
        *one-to-many元素: 作用:指定当前实体类与目标实体类的映射关系
                    属性:class:指定目标实体类的名称
二.多对一关系映射
    1.配置文件中的配置:
  1. <many-to-one name="customer"class="CstCustomer" column="lkm_cust_id"/>
    2.元素:
        *<many-to-one />:作用:当前映射实体和实体中的引用之间的关系
            属性:name:指定关系对象引用类型的名称
                    class:引用对象的类型
                    column:指定多的一方中外键的字段
三.关系映射的级联配置
    1.set元素里面的属性配置(一对多)
        cascade:级联操作      
                取值:save-update:级联保存操作
                        delete:级联删除
  1. <set name="linkmans" table="cst_linkman" cascade="save-update,delete">
  2. <key column="lkm_cust_id"></key>
  3. <one-to-many class="CstLinkMan"/>
  4. </set>
    2.多对一关系映射
        <many-to-one>中元素的属性:
                cascade:级联操作
                        取值:save-update:级联保存更新
  1. <many-to-one name="customer"class="CstCustomer" column="lkm_cust_id" cascade="save-update"/>
    3.一对多双向关系映射放弃维护权利
        set元素的属性:inverse:是否放弃维护的权利
                                        取值:true:放弃     false:不放弃(默认值)
        注意:在一对多关系映射上,inverse属性永远配置在set元素上
  1. <set name="linkmans" table="cst_linkman" cascade="save-update" inverse="true">
  2. <key column="lkm_cust_id"></key>
  3. <one-to-many class="CstLinkMan"/>
  4. </set>
    4.多对多关系映射
        set元素:映射集合元素;
            属性:name:指定集合属性的名称           table:指定的是中间表的名称
        key元素:用于指定外键
            属性:  column:指定当前实体类在中间表的外键
        many-to-many元素:指定当前实体类与集合属性的关系
            属性:class:指定集合中元素的类型        column:指定的是集合属性元素在中间表的外键名称
  1. <set name="roles" table="sys_user_role">
  2. <key column="user_id"></key>
  3. <many-to-many class="SysRole" column="role_id"></many-to-many>
  4. </set>

四.知识点
    1.HQL:Hibernate Query Language
    2.query对象:Query query = session.createQuery("from CRMCustomer");
    3.关于缓存
        *什么时候用缓存:非敏感数据/不经常修改的数据/出现的一些小错误是在允许的范围之内
        *与一级缓存有关的方法:
            *flush()  --它的出现,表明手动执行快照机制
            *refresh()  --是用数据库中的数据去修改缓存的数据,同时也会修改内存对象
            *evict(Object entity)  --清除一级缓存中指定的对象
            *close()  --关闭session,证明session已经不能用了
            *clear()  --清除session中的所有的一级缓存
    4.hibernate对象状态的判断依据:是否有OID ,是否和session有关系
    5.merge(Object entity)  --把两个具有相同OID的对象进行合并
    6.一对多关系映射中出现的问题(单向关联关系)
            *先保存联系人,在保存客户时,会多一条update的语句
                解决:先保存客户,再保存联系人
            *修改一个联系人,为其重新分配一个客户时,就会报错,因为一个持久态或者脱管态对象关联了一个临时态对象
                解决:在映射文件中配置级联更新:cascade="save-update"
    6.一对多关系映射中出现的问题(双向关联关系)
            *先保存联系人,在保存客户时,会多一条update的语句
                解决:让有集合的一方的集合放弃维护关联关系的权利:inverse="true"
             *修改一个联系人,为其重新分配一个客户时,就会报错,因为一个持久态或者脱管态对象关联了一个临时态对象
                解决:在映射文件中配置级联更新:cascade="save-update"
五.Hibernate的检索方式(五种)
    1.OID检索
          get(Customer.class,1l)或者load(Customer.class,2l)
    2.对象导航检索
        根据条件查找对象实体类,然后根据实体类关联的对象进行对象检索
    3.HQL(Hibernate Query Language) 检索
        *基本查询:
            Query query = session.createQuery("from Customer");
            List<Customer> list = query.list();
        *排序查询:
            Query query = session.createQuery("from Customer order by cust_id desc");
        *条件查询:
            *按照位置绑定参数:
                Query query = session.createQuery(from Customer where cust_id=?);
                query.setString(0,2l);
                或者:query.setParameter(0,2l);
            *按照名称绑定参数:
                 Query query = session.createQuery("from Customer where name=:name");
                query.setParameter("name","");
        *分页查询:
                Query query = session.createQuery("from Customer order by cust_id");
                query.setFirstResult(0);
                query.setMaxResults(3);
        *统计查询:
                Query query = session.createQuery("select count(*) from Customer");
                Long num = (Long)query.uniqueResult();
        *投影查询:
            要求:实体类必须要有对应参数的构造方式
                List<Customer> customers = session.createQuery("select new Customer(cust_id,cust_name) from Customer ").list();
    4.QBC(Query By Criteria)检索
     *简单查询:
            Criteria criteria = session.createCriteria(Customer.class);
            List<Customer> customers = criteria.list();
        *条件查询:
            Criteria criteria = session .createCriteria(Customer.class)
            criteria.add(Restrictions.eq("custName",""))
            criteria.add(Restrictions.gt("custId",1l));
            criteria.add(Restrictions.like("cusName","%小%"))
        *分页查询:
            Criteria criteria = session.createCriteria(Customer.class);
            criteria.setFirstResult(0);
            criteria.setMaxResult(4);
        *排序查询:
            Criteria criteria = session.createCriteria(Customer.class)
            criteria.addOrder(Order.desc("custId"))
        *投影查询:
            Criteria criteria = session.createCriteria(Customer.class);
            criteria.setProjection(
                Projections.projectionlist()
                    .add(Projections.property("custName"))
                    .add(Projections.property("custId"))
                );
        *离线条件查询:(DetachedCriteria---SSH整合经常使用,可以脱离session进行参数设置)
  1. publicvoid test05(){
  2. //获得一个离线条件查询的对象
  3. DetachedCriteria dc =DetachedCriteria.forClass(CRMCustomer.class);
  4. dc.add(Restrictions.eq("custId",2l));
  5. Session session =HibernateUtils.getCurrentSession();
  6. Transaction ts = session.beginTransaction();
  7. //离线条件查询对象与session绑定
  8. List<CRMCustomer> list = dc.getExecutableCriteria(session).list();
  9. for(CRMCustomer cust : list){
  10. System.out.println(cust);
  11. }
  12. ts.commit();
  13. }

    5.SQL检索
        *就是一般的SQL语句
六.HQL的连接查询:
    *内连接:
        *隐式内连接:select * from customer c,linkman l where c.id=l.id
        *显式内连接:select * from  customer c inner join linkman l on c.id=l.id   
        *迫切内连接:select distinct c from customer c inner  join fetch c.linkman
    *内连接与迫切内连接的区别:
        *内连接:发送的就是内连接的语句,封装的时候将每条记录封装到一个Object[]数组中,最后得到一个List<Object[]>
        *迫切内连接:发送的也是内连接的语句,在join后添加了fetch关键字,Hibernate会将每条数据封装到对象中(需要去掉重复值) 
七.Hibernate的抓取策略(提升性能手段)
    *检索策略:当使用某种检索策略时,所带来的好处
    1.类级别检索策略
        *查询的时机:
            立即加载:不管用不用,只要查询一个实体,就把当前实体中的所有字段数据查询出来
            延迟加载:如果只用当前实体类的OID,则不会发起查询,当需要实体类中其他字段时,才会发起查询
        *明确:类级别的检索策略,只涉及当前类的字段数据,不涉及关联对象的数据
        *涉及的方法
            *get:永远都是立即加载,不管用不用对象中的其他数据,都查出来
            *load:默认情况下是延迟加载,可以通过修改配置文件,改为立即加载
                配置属性中修改class的属性lazy,默认值是true,改为false就是立即加载
            *query.list():永远都是立即加载
    2.关联级别的检索策略
        *根据少的一方获取多的一方(一对多,多对多)
            *配置:修改配置文件都是针对 set元素中的属性
                    *lazy属性:查询的时机
                    *fetch属性:查询的方式

序号

lazy的取值

fetch的取值

说明(都是以客户联系人一对多为例)

1

true(默认值)

select(默认值)

时机:用时才真正去查询联系人。

语句形式:多条SQL语句

Batch-size:设置批量检索的深度。(建议3~10之间)

2

false

select(默认值)

时机:不管用不用,查询客户时都立即查询联系人。

语句形式:有1条查询客户的和多条查询联系人的select语句。

Batch-size:设置批量检索的深度。(建议3~10之间)

3

extra

select(默认值)

时机:用什么信息,查什么信息。只查询必要的。

语句形式:有1条查询客户的和多条查询联系人的select语句。

batch-size:设置批量检索的深度。(建议3~10之间)

4

true

subselect

时机:用时才真正去查询联系人。

语句形式:子查询

batch-size:无效

5

false

subselect

时机:不管用不用联系人,查询客户时都立即查询联系人。

语句形式:子查询

batch-size:无效

6

extra

subselect

时机:用什么信息,查什么信息。只查询必要的。

语句形式:子查询

batch-size:无效

7

true|false|extra

join(当join有效时,根本不看lazy属性)

时机:无效。因为连接查询,一次就是两张表及以上。

语句:left outer join

batch-size:无效

注意:Query查询会忽略join的存在。当join无效时,lazy就有效了。

     *使用原则:延迟加载
        *根据多的一方获取少的一方(多对一,一对一)
            *配置:在<many-to-one>元素中配置lazy属性和fetch属性
            *配置说明

序号

lazy

fetch

说明(用的是客户和联系人的一对多关系)

1

proxy

select

时机:

   对象类级别的策略:true。延迟加载。得到的是代理对象。

   对象类级别的策略:false。立即加载。得到就是类对象。

语句:

   多条SQL语句

 

2

false

select

时机:立即加载。与对象类级别的策略无关。

语句:多条SQL语句。

3

true|false|extra

join(当join有效时,根本不看lazy属性)

时机:无效。因为连接查询,一次就是两张表及以上。

语句:left outer join

    *使用原则:立即加载

八.Hibernate中使用c3p0数据源
    1.copy必要的jar包
    2.在hibernate主配置文件中配置
        <property name="hibernate.connection.provider_class">
            org.hibernate.connection.C3P0ConnectionProvider
        </property>
    3.验证数据源是否配置成功
  1. @Test
  2. publicvoid test(){
  3. Session s =HibernateUtils.getSession();
  4. s.doWork(newWork(){
  5. @Override
  6. publicvoid execute(Connection conn)throwsSQLException{
  7. System.out.println(conn.getClass().getName());
  8. conn.close();
  9. }
  10. });
  11. }
九.hibernate中的二级缓存
    1.hibernate中的缓存结构
    2.二级缓存的数据被多线程共享,就必须有一定的事务访问策略  
  
    3.适合放入二级缓存中的数据
        *很少被修改
        *不是很重要的数据,允许出现偶尔的并发问题
    4.类缓冲区:里面存的是对象中的数据,而不是对象
        *get和load都可以存和取二级缓存中的数据
        *Query.list("from CstCustomer")只能存不能取,因为是动态查询
    5.集合缓冲区
        *一对多关系映射中,操作多的一方就是集合.对应的实体类也要开启缓存配置
    6.更新时间戳:当我们修改以及缓存中的数据时,会自动同步二级缓存中的数据,用的是时间戳原理
    7.查询缓存区
        *解决的问题:Query查询只能查不能取,因为语句是动态的
        *解决办法:按照语句进行存储,使用Map<String,Object>,key是sql语句,value是查询的结果集,这个map就是查询缓存区,默认是关闭的
        *使用:在hibernate.cfg.xml中配置
            <property name="hibernate.cache.use_query_cache">true</property>
            dao层设置:query.setCacheable(true)
0 0
原创粉丝点击