hibernate学习记录

Class.hbm.xml

关系配置
    <class>
<!-- 集合,一对多关系,在配置文件中配置 -->
        <!-- 
            name属性:集合属性名
            column属性: 外键列名
            class属性: 与我关联的对象完整类名
         -->
         <!-- 
            级联操作:   cascade
                save-update: 级联保存更新
                delete:级联删除
                all:save-update+delete
            级联操作: 简化操作.目的就是为了少些两行代码.
            结论: 简化操作.一定要用,用save-update,不建议使用delete.
          -->
          <!-- inverse属性: 配置关系是否维护. 
                true: customer不维护关系
                false(默认值): customer维护关系

            inverse属性: 性能优化.提高关系维护的性能.
            原则: 无论怎么放弃,总有一方必须要维护关系.
            一对多关系中: 一的一方放弃.也只能一的一方放弃.多的一方不能放弃.
          -->
          <!-- 
        lazy属性: 决定是否延迟加载
            true(默认值): 延迟加载,懒加载
            false: 立即加载
            extra: 极其懒惰
        fetch属性: 决定加载策略.使用什么类型的sql语句加载集合数据
            select(默认值): 单表查询加载
            join: 使用多表查询加载集合
            subselect:使用子查询加载集合
     -->
     <!-- batch-size: 抓取集合的数量为3.
            抓取客户的集合时,一次抓取几个客户的联系人集合.
      -->
        <set name="linkMens" lazy="" fetch="" batch-size= "" inverse="true" cascade="delete"  >
            <key column="lkm_cust_id" ></key>
            <one-to-many class="LinkMan" />
        </set>
<!-- 多对一 -->
        <!-- 
            name属性:引用属性名
            column属性: 外键列名
            class属性: 与我关联的对象完整类名
         -->
          <!-- 
            级联操作:   cascade
                save-update: 级联保存更新
                delete:级联删除
                all:save-update+delete
            级联操作: 简化操作.目的就是为了少些两行代码.
            结论: 简化操作.一定要用,用save-update,不建议使用delete.
          -->
          <!-- 多的一方: 不能放弃维护关系的.外键字段就在多的一方.  -->
        <many-to-one name="customer" column="lkm_cust_id" class="Customer"  >
        </many-to-one>
<!-- 多对多关系表达 -->
        <!-- 
            name: 集合属性名
            table: 配置中间表名
            key
             |-column:外键,别人引用"我"的外键列名
             class: 我与哪个类是多对多关系
             column:外键.我引用比人的外键列名
         -->
         <!-- cascade级联操作:
                    save-update: 级联保存更新
                    delete:级联删除
                    all:级联保存更新+级联删除
            结论: cascade简化代码书写.该属性使不使用无所谓. 建议要用只用save-update.
                 如果使用delete操作太过危险.尤其在多对多中.不建议使用.
                     -->
        <set name="roles" table="sys_user_role" cascade="save-update" >
            <key column="user_id" ></key>
            <many-to-many class="Role" column="role_id" ></many-to-many>
        </set>
<!-- 使用inverse属性
            true: 放弃维护外键关系
            false(默认值):维护关系

        结论: 将来在开发中,如果遇到多对多关系.一定要选择一方放弃维护关系.
             一般谁来放弃要看业务方向. 例如录入员工时,需要为员工指定所属角色.
             那么业务方向就是由员工维护角色. 角色不需要维护与员工关系.角色放弃维护
         -->        
        <set name="users" table="sys_user_role" inverse="true" >
            <key column="role_id" ></key>
            <many-to-many class="User" column="user_id" ></many-to-many>
        </set>
    </class>

关联例子

//3操作
        Customer c = new Customer();
        c.setCust_name("课");    
        LinkMan lm1 = new LinkMan();
        lm1.setLkm_name("王");   
        LinkMan lm2 = new LinkMan();
        lm2.setLkm_name("刘");
        //表达一对多,客户下有多个联系人
        (如果客户放弃维护与联系人的关系. 维护关系的代码可以省略)
        c.getLinkMens().add(lm1);
        c.getLinkMens().add(lm2);
        //表达对对对,联系人属于哪个客户
        lm1.setCustomer(c);
        lm2.setCustomer(c);
        session.save(c);
        session.save(lm1);(未级联都得保存)
        session.save(lm2);
//3操作
        //1> 获得要操作的客户对象
        Customer c = session.get(Customer.class,1l);
        //2> 创建联系人
        LinkMan lm1 = new LinkMan();
        lm1.setLkm_name("好");
        //3> 将联系人添加到客户,将客户设置到联系人中
        c.getLinkMens().add(lm1);
        lm1.setCustomer(c);
        //4> 执行保存
        session.save(lm1);
//3操作
        //1> 获得要操作的客户对象
        Customer c = session.get(Customer.class,1l);
        //2> 获得要移除的联系人
        LinkMan lm = session.get(LinkMan.class, 3l);
        //3> 将联系人从客户集合中移除
        c.getLinkMens().remove(lm);
        lm.setCustomer(null);
 Customer.hbm.xml
<?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">
   <!-- 配置表与实体对象的关系 -->
   <!-- package属性:填写一个包名.在元素内部凡是需要书写完整类名的属性,可以直接写简答类名了. -->
<hibernate-mapping package="cn.example.domain" >
    <!-- 
        class元素: 配置实体与表的对应关系的
            name: 完整类名
            table:数据库表名
     -->
    <class name="Customer" table="cst_customer" >
        <!-- id元素:配置主键映射的属性
                name: 填写主键对应属性名
                column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名
                type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
                        每个类型有三种填法: java类型|hibernate类型|数据库类型
                not-null(可选):配置该属性(列)是否不能为空. 默认值:false
                length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
         -->
        <id name="cust_id"  >
            <!-- generator:主键生成策略.就是每条记录录入时,主键的生成规则.(7个)
                    identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.
                    sequence: Oracle中的主键生成策略.
                    increment(了解): 主键自增..           
                    hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
                    native:hilo+sequence+identity 自动三选一策略.
                    uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
                    assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.

             -->
            <generator class="native"></generator>
        </id>
        <!-- property元素:除id之外的普通属性映射
                name: 填写属性名
                column(可选): 填写列名
                type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
                        每个类型有三种填法: java类型|hibernate类型|数据库类型
                not-null(可选):配置该属性(列)是否不能为空. 默认值:false
                length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
         -->
        <property name="cust_name" column="cust_name" >
            <!--  <column name="cust_name" sql-type="varchar" ></column> -->
        </property>
        <property name="cust_source" column="cust_source" ></property>
        <property name="cust_industry" column="cust_industry" ></property>
        <property name="cust_level" column="cust_level" ></property>
        <property name="cust_linkman" column="cust_linkman" ></property>
        <property name="cust_phone" column="cust_phone" ></property>
        <property name="cust_mobile" column="cust_mobile" ></property>


</hibernate-mapping>

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 
        #hibernate.dialect org.hibernate.dialect.MySQLDialect
        #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
        #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
        #hibernate.connection.driver_class com.mysql.jdbc.Driver
        #hibernate.connection.url jdbc:mysql:///test
        #hibernate.connection.username gavin
        #hibernate.connection.password
         -->
         <!-- 数据库驱动 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
         <!-- 数据库url -->
        <property name="hibernate.connection.url">jdbc:mysql:///hibernate_32</property>
         <!-- 数据库连接用户名 -->
        <property name="hibernate.connection.username">root</property>
         <!-- 数据库连接密码 -->
        <property name="hibernate.connection.password">1234</property>
        <!-- 数据库方言
            不同的数据库中,sql语法略有区别. 指定方言可以让hibernate框架在生成sql语句时.针对数据库的方言生成.
            sql99标准: DDL 定义语言  库表的增删改查
                      DCL 控制语言  事务 权限
                      DML 操纵语言  增删改查
            注意: MYSQL在选择方言时,请选择最短的方言.
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>


        <!-- #hibernate.show_sql true 
             #hibernate.format_sql true
        -->
        <!-- 将hibernate生成的sql语句打印到控制台 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 将hibernate生成的sql语句格式化(语法缩进) -->
        <property name="hibernate.format_sql">true</property>
        <!-- 
        ## auto schema export  自动导出表结构. 自动建表
        #hibernate.hbm2ddl.auto create      自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用)
        #hibernate.hbm2ddl.auto create-drop 自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用)
        #hibernate.hbm2ddl.auto update(推荐使用) 自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据).
        #hibernate.hbm2ddl.auto validate    校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败.
         -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- 指定hibernate操作数据库时的隔离级别 
            #hibernate.connection.isolation 1|2|4|8     
            0001    1   读未提交
            0010    2   读已提交
            0100    4   可重复读
            1000    8   串行化
         -->
         <property name="hibernate.connection.isolation">4</property>
         <!-- 指定session与当前线程绑定 -->
         <property name="hibernate.current_session_context_class">thread</property>
        <!-- 引入orm元数据
            路径书写: 填写src下的路径
         -->
        <mapping resource="cn/example/domain/Customer.hbm.xml" />

    </session-factory>
</hibernate-configuration>

API:

  • Configuration功能: 配置加载类.用于加载主配置,orm元数据加载
    (Configuration).configure():读取指定主配置文件 => 空参加载方法,加载src下hibernate.cfg.xml文件
    根据配置信息,创建 SessionFactory对象
    SessionFactory sf = conf.buildSessionFactory();

  • SessionFactory功能: 用于创建操作数据库核心对象session对象的工厂.
    简单说功能就一个—创建session对象
    注意:1.sessionfactory 负责保存和使用所有配置信息.消耗内存资源非常大.
    2.sessionFactory属于线程安全的对象设计.
    结论: 保证在web项目中,只创建一个sessionFactory.
    打开一个新的session对象
    Session session =sf.openSession();
    获得一个与线程绑定的session对象
    Session session =sf.getCurrentSession();

  • session对象功能: 表达hibernate框架与数据库之间的连接(会话).session类似于JDBC年代的connection对象. 还可以完成对数据库中数据的增删改查操作.session是hibernate操作数据库的核心对象
    session获得操作事务的Transaction对象
    session.save(class);增
    session.delete(class);删
    session.update(class);改
    session.saveorupdate(class);
    session.get(Customer.class, 1l);查
    session.load(Customer.class, 1l);查使用时加载

    获得操作事务的tx对象(未开启事物,建议使用下一种)
    Transaction tx = session.getTransaction();
    开启事务并获得操作事务的tx对象(建议使用)
    Transaction tx2 = session.beginTransaction();
    

例子:

public void fun(){
        //1 创建,调用空参构造
        Configuration conf = new Configuration().configure();
        //2 根据配置信息,创建 SessionFactory对象
        SessionFactory sf = conf.buildSessionFactory();
        //3 获得session
        Session session = sf.openSession();
        //4 session获得操作事务的Transaction对象
        //获得操作事务的tx对象
        //Transaction tx = session.getTransaction();
        //开启事务并获得操作事务的tx对象(建议使用)
        Transaction tx2 = session.beginTransaction();
        //----------------------------------------------
        //1 获得要修改的对象
        Customer c = session.get(Customer.class, 1l);
        //2 修改
        c.setCust_name("程序员");
        //3 执行update
        session.update(c);
        //----------------------------------------------
        tx2.commit();//提交事务
        session.close();//释放资源
        sf.close();//释放资源
    }

HQL例子

问号占位符
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1> 书写HQL语句
        String hql = " from Customer where cust_id = ? "; // 查询所有Customer对象
        //2> 根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //设置参数
        //query.setLong(0, 1l);
        query.setParameter(0, 1l);
        //3> 根据查询对象获得查询结果
        Customer c = (Customer) query.uniqueResult();

        System.out.println(c);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
//命名占位符
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1> 书写HQL语句
        String hql = " from Customer where cust_id = :cust_id "; // 查询所有Customer对象
        //2> 根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //设置参数
        query.setParameter("cust_id", 1l);
        //3> 根据查询对象获得查询结果
        Customer c = (Customer) query.uniqueResult();

        System.out.println(c);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
//分页
        //1> 书写HQL语句
        String hql ="from Customer order by cust_id asc"; // 查询所有Customer对象
        //2> 根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //设置分页信息 limit ?,?
        query.setFirstResult(1);
        query.setMaxResults(1);
        //3> 根据查询对象获得查询结果
        List<Customer> list =  query.list();

Criteria查询(单表条件查询)

//HQL语句中,不可能出现任何数据库相关的信息的
    // >                gt
    // >=               ge
    // <                lt
    // <=               le
    // ==               eq
    // !=               ne
    // in               in
    // between and      between
    // like             like
    // is not null      isNotNull
    // is null          isNull
    // or               or
    // and              and
        //创建criteria查询对象
        Criteria criteria = session.createCriteria(Customer.class);
        //添加查询参数 => 查询cust_id为1的Customer对象
        criteria.add(Restrictions.eq("cust_id", 1l));
        //执行查询获得结果
        Customer c = (Customer) criteria.uniqueResult();
//分页
        //创建criteria查询对象
        Criteria criteria = session.createCriteria(Customer.class);
        //设置分页信息 limit ?,?
        criteria.setFirstResult(1);
        criteria.setMaxResults(2);
        //执行查询
        List<Customer> list = criteria.list();
//查询总记录数
        //创建criteria查询对象
        Criteria criteria = session.createCriteria(Customer.class);
        //设置查询的聚合函数 => 总行数
        criteria.setProjection(Projections.rowCount());
        //执行查询
        Long count = (Long) criteria.uniqueResult();
//离线Criteria
//Service/web层
        DetachedCriteria **dc**  = DetachedCriteria.forClass(Customer.class);
        dc.add(Restrictions.idEq(6l));//拼装条件(全部与普通Criteria一致)
//dao层
Criteria c = **dc**.getExecutableCriteria(session);

DetachedCriteria (多表关联)

第一步为对象中的命名建立别名
dc.createAlias("region", "r");
//指定封装的方式,这种为对象嵌套例如  (学校(班级(学生名)))如果没有为(学校)(班级(学生名))
detachedCriteria.setResultTransformer(DetachedCriteria.ROOT_ENTITY);

原生SQL查询

        //1 书写sql语句
        String sql = "select * from cst_customer where cust_id = ? ";   
        //2 创建sql查询对象
        SQLQuery query = session.createSQLQuery(sql);
        query.setParameter(0, 1l);
        //指定将结果集封装到哪个对象中
        query.addEntity(Customer.class);
        //3 调用方法查询结果(query.list()没有指定addEntity返回Object[])
        List<Customer> list = query.list();
//Hibernate Utils 
public class HibernateUtils {
    private static SessionFactory sf;
    static{
        //1 创建,调用空参构造
        Configuration conf = new Configuration().configure();
        //2 根据配置信息,创建 SessionFactory对象
         sf = conf.buildSessionFactory();
    }
    //获得session => 获得全新session
    public static Session openSession(){
                //3 获得session
                Session session = sf.openSession();         
                return session; 
    }
    //获得session => 获得与线程绑定的session
    public static Session getCurrentSession(){
        //3 获得session
        Session session = sf.getCurrentSession();
        return session;
    }
}
  • hibernate是一款orm框架
  • orm:object relationg mapping. 对象关系映射
  • HQL查询-hibernate Query Language(多表查询,但不复杂时使用)
  • Criteria查询(单表条件查询)
  • 原生SQL查询(复杂的业务查询)

hql多表(略)

//----------------------------------------------------
        String hql = " from Customer c right join c.linkMens ";
        (left join)(inner join)
        Query query = session.createQuery(hql);
        List<Object[]> list = query.list();
//HQL 迫切内连接 => 帮我们进行封装.返回值就是一个对象
    public void fun2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------
        String hql = " from Customer c inner join fetch c.linkMens ";

        Query query = session.createQuery(hql);

        List<Customer> list = query.list();
//集合级别的关联
    //fetch:select 单表查询
    //lazy:true 使用时才加载集合数据.
//集合级别的关联
        //fetch:select 单表查询
        //lazy:false 立即记载集合数据

//集合级别的关联
        //fetch:select 单表查询
        //lazy:extra 极其懒惰.与懒加载效果基本一致. 如果只获得集合的size.只查询集合的size(count语句)

//集合级别的关联
        //fetch:join    多表查询
        //lazy:true|false|extra 失效.立即加载.

    //fetch: subselect 子查询
        //lazy: true 懒加载

//fetch: subselect 子查询
        //lazy: false 立即加载

//fetch: subselect 子查询
        //lazy: extra 极其懒惰
<!-- 
        fetch 决定加载的sql语句
            select: 使用单表查询
            join : 多表查询
        lazy  决定加载时机
            false: 立即加载
            proxy: 由customer的类级别加载策略决定.
         -->
        <many-to-one name="customer" column="lkm_cust_id" class="Customer" fetch="join" lazy="proxy"  >
        </many-to-one>

//fetch:select  单表查询
    //lazy:proxy  
        //customer-true 懒加载

//fetch:join    多表
    //lazy: 失效  

//fetch:select  单表查询
    //lazy:proxy  
        //customer-false 立即加载

hibernate过滤
悲观锁在session.method里加锁就行 安全,并发效率低
乐观锁在class.hbm.xml里<id>后加<version> 安全比悲观低,并发高

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值