Hibernate 干货

一 .hibernate概念:

hibernate应用在javaee 三层框架中的dao层(web 层 --service层--dao层),在dao层实现对数据库的CRUD操作。hibernate是对jdbc的封装,使用hibernate的好处,不需要写jdbc复杂的代码,不需要写sql语句实现。 hibernate是开源的轻量级框架。

版本:hibernate3.x hibernate4.x hibernate5.x 其中4.x不稳定不建议使用

orm: object relational mapping  对象关系映射  hibernate使用的就是orm思想对数据库进行CRUD操作

简单说:让实体类和表进行一一对应关系(实体类名--数据库表名  实体类中属性名--表中字段名)

使用配置文件来完成这种对应关系

二.配置文件

hibernate的核心配置文件

    hibernate.cfg.xml  hibernate核心配置文件 路径:src目录下文件名称固定不变
    <hibernate-configuration>  <!-- hibernate 核心配置文件的跟路径 -->
        <session-factory> <!--所有的配置信息都写在该目录下 -->
     
            <!-- 1.连接数据库-->
            <property name= "connection.driver_class" >com.mysql.jdbc.Driver</property>
            <property name= "connection.url" >jdbc:mysql:///hibernate</property>
            <property name= "connection.username" >root</property>
            <property name= "connnection.password" >root</property>
     
            <!-- 2. hibernate 其他参数配置 -->
            <property name= "show-sql" >true</property>
            <property name= "format-sql" >true</property>
            <property name= "hibernate.hbm2ddl.auto" >ture</property><!--自动建表,存在更新没有创建-->
            <property name= "dialect" >org.hibernate.dialect.mysqlDialect</property><!--方言 分页查询 mysql 种用limit  oracle中用rownum -->
            <property name= "hibernate.current_session_context_class" >thread</property><!--session是单线程对象  所以需要绑定本地线程-->
     
            <!-- 3. mapping 映射文件引入 -->
            <mapping resource="cn/ss/entity/User.hbm.xml"/><!--路径用/分割开 因为是文件路径-->

hibernate映射配置文件

    hibernate 映射配置文件 即实体类的映射文件一般和实体类所在路径在同一个包下
    例如:User.hbm.xml  格式:实体类名+.hbm.xml 固定格式
    <!-- 配置类和表的对应关系 -->
    <hibernate-mapping><!-- hibernate映射文件的根目录-->
        <class name="cn.ss.entity.User" table="t_user">
            <!--所有对应 类属性和表字段关系都写在里面
                name 属性: 映射文件对应的实体类的全路径
                table 属性 : 数据库对应的表名
            -->
             <id name="uid" column="uid">
              <!--id 标识 实体类对象的唯一标识
                    name属性 : 实体类的属性名
                    column 属性 : 属性对应表中是字段
                -->
                <generator class="native"></generator>
            </id>
     
            <!--配置其他 实体类属性和字段名对应关系 -->
            <property name="uname" column="uname"></property>
            ... ...
        </class>

主键生成策略:

    increment: 由long int short 类型使用,由hibernate自动递增(每次加1) 线程不安全 建议测试使用 identity:由DB2 mysql  sql server 等数据库支持自增长类型的数据库使用的生成器,要求主键定义为自增长生成器类型
    sequence:由oracle 等数据库支持序列的数据库使用。
    native:当使用native hibernate会自动识别数据库并用对应的主键生成策略从而识别主键生成识别符
    uuid:由hibernate 采用128位uuid算法 生成的识别符
    assignied: 由java 程序生成的识别符,如果默认id没写generator 属性则默认值位assignied

 

三 hibernate 核心api使用

Configuration  SessionFactory Session Transaction

1.Configuration 读取hibernate核心配置文件用的类

    Configuration cfg = new Configuraion();
    cfg.configure(); //hibernate.cfg.xml 名称固定 位置固定在src下才可以读取到

2.SessionFactory 执行过程中创建表,特别消耗资源,建议一个项目只创建一共sesionFactroy对象. 可以创建session

cfg.buildSessionFactory();

写在工具类里面且一个项目只创建一个sessionFactroy 对象的实现代码

    public class HibernateUtils{//hibernate 工具类
     
        private static Configuration cfg;
        private static Sessionfactory sessionFactory;
        private static Session session;
     
        static {//在静态代码块中创建可以保证类加载的时候只创建一次,保证唯一性
            cfg = new Configuration();
            sessionFactory = cfg.buildSessionFactory();
        }
     
     
        public static SessionFactory getSessionFactory(){
            return sessionFactroy;
     
        }
        public static Session getSession(){
        //session = sessionFactory.OpenSession(); 线程不安全不建议使用
        return sessionFactory.getCurrentSession();//绑定本地线程 且线程安全 不需要手动关闭session     
        //否则写了会报错 session.close();
     
        }
     
    }

3.Session 类相当于jdbc中的connection hibernate中的session是单线程的,所以需要绑定本地线程

然后调用session的方法操作对象

相关方法:

1.获取对象  get(类名.class,主键值)

2.保存save(对象)

3.修改update(对象)saveOrUpdate(对象)

4.删除delete(对象)--注意删除的时候需要先查询出对象才可以删除

 

4.Transaction 事务类

只有开启事务之后 才可以操作session对应的方法

    /**事务开启*/
     
    Transaction tx = session.beginTransaction();
     
     
     
    /** 提交事务**/
     
    tx.commit();
     
     
    /** 回滚事务**/
     
    tx.rollback();

 事务的特性:原子性 一致性 隔离性 持久性

四 hibermate的对像状态和缓存机制

hibernate对对象由三种状态:

    瞬时态:对象里即没有id 主键值 ,又没又在session对象中
        User u = new User(); new出来的都是瞬时态对象
        u.setname("wangwu");并里面没有id
     
    持久态:对象里即有id主键值,又在session的对象中
     
        持久态对象可以实现立即刷新,不需要save() update()等
        User u = session.get(User.class,1);
        u.sertname("lisi");
     
    托管态:对象中有id主键值,但没在session的对象中
     
        User u = new User();
        u.serid(5); // 对象中有id

hibernate的缓存:

第一种:一级缓存 在session 对象中,生命周期同session,是持久态对象自动更新的依据。实现原理:在创建session对象时会同时创建session的一级缓存和一个副本快照区,当session对象调用方法得到持久态对象时 首先会到一级缓存中查找是否存在该对象,如果没有就存放到一级缓存中同时复制到副本快照区,当对象修改后,首先到副本区查看对象是否与该对象一致,如果一致则不做修改,如果不一致则实行自动更新操作,把数据更新到数据库中

第二种: 二级缓存 在sessionFactory对象中,生命周期同sessionFactory,一般很少使用

五 hibernate 表与表之间的关系 及级联操作

一对多 多对多 一对一

一对多

    一对多: 客户和联系人的关系 一个客户可以有多个联系人 但是一个联系人只属于一个客户
    配置文件中操作
     
    在一的一方
    客户方实体类
    Customer  class
    添加联系人Set集合属性
    private Set<LinkMan> setLinkMan = new HashSet<LinkMan>();//无序 唯一性
     
    客户方映射配置文件
    Customer.hbm.xml
    添加set标签
    <set name = "setLinkMan" cascade="save-update,delete" inverse="false" bach-size="10">
    <!--cascade属性:级联操作  级联保存或修改 级联删除
     inverse属性:不放弃关系的维护 默认false  true:表示放弃对关系的维护
    这两个属性一般都放在一的一方
     
        bach-size:批量抓起 数据越大 执行sql 越少 效率越高
    -->
        <key column = "clid"></key><!-- 联系人表外键名称-->
        <one-to-many class="cn.ss.entity.LinkMan"/>
     
     </set>
     
     
    在多的一方
    联系人实体类
    LinkMan class
    添加所属客户属性
    private Customer customer;
     
     
    联系人映射配置文件
    LinkMan.hbm.xml
    添加many-to-one 标签
    <many-to-one name="customer" class="cn.ss.enetiy.Customer" column="clid"/>
     
     
    java代码
    Customer baidu = new Customer();
    baidu.sertname("baidu");
    LinkMan lucy =  new Link Man();
    lucy.setname("lucy");
    LinkMna wangcai = new LinkMan();
    wangcai.setname("wangcai');
    baidu.getSetLinkMan().add(lucy);
    baidu.getSetLinkMan().add(wangcai);
    //持久态对象 自动更新 不需要save() 方法 实现了级联保存操作
    级联删除类似

多对多

    多对多: 用户的和角色的关系 一个用户可以有多个角色 ,一个角色也可以有多个用户
    配置中间中操作
     
    在用户方
    用户实体类
    User class
    添加角色类set集合
    private set<Role> setRole = new HashSet<Role>();
     
    用户映射配置文件
    User.hbm.xml
    添加set标签
    <set name="setRole" table ="user_role" casecade="save-update" inverse="true">
    <!--cascade 级联操作 一般多对多时不会用到级联删除 -->
        <!-- table 表示 多对多关系中的第三张表维护多对多关系 -->
        <key column= "userid"></key>
        <many-to-many class="cn.ss.entity.Role" column="roleid"/>
    </set>
     
    角色方
    角色实体类
    Role class
    添加用户set集合
    private Set<Use> setUser = new HashSet<User>();
     
    角色映射配置文件
    Role.hbm.xml
    添加set标签
    <set name="setUser" table="user_role">
        <key column= "roleid"></key>
        <many-to-many class="cn.ss.entity.User" column="userid"/>
    </set>
     
     
    java代码
    User u1 = new User();
    u1.setname("u1");
    User u2 = new User();
    u2.setname("u2");
     
    Role r1 = new Role();
    r1.setName("r1");
    Role r2 = new Role();
    r2.setName("r2");
    Role r3 = new Role();
    r3.setName("r3");
     
     
    u1.getSetRole().add(r1);
    u1.getSetRole().add(r2);
    u2.getSetRole().add(r2);
    u2.getSetRole().add(r3);
     
    //以下代码可以不写
    session.save(u1);
    session.save(u2);
     
     
     

六 hibernate其他api查询对象

Query Crieator SQLQuery

Query对象 使用的是hql语句 只操作实体类和属性

    Query对象  --- HQL查询
    //1.hql语句 创建
    String hql = "from User"; //from+实体类  查询所有
     
    //2 创建Query对象
    Query query = session.createQuery(hql);
     
    //3.调用对象方法返回结果
    List <User>  list = query.list();
     
     
    hql语句:
    1.查询所有 “form User”  from+实体类类名
    2.条件查询 "from User where uid = ?" 条件语句where+实体类属性名=? ?是占位符
        需要设置值 用query.setParameter(下标从0开始,对应属性值);
        如果多条用 List<User> list = query.list();  
        如果唯一值 Object obj = query.uniqueResult(); 注意long型数据
    3.模糊查询 “form User where name like ?”
        ? 占位符值设置:query.setParameter(下标从0开始,“%白%”);
    4.排序查询 “from User Order by uid” //form+实体类名+order by +属性名 asc/desc;
    5.分页查询 使用的是query对象的两个方法
        query.setFirstResult(0);//从0开始查
        query.setMaxResults(3);//每页查找3条记录
    6.投影查询 “select uid,unmae from User” //select+属性名1,属性名2 form+实体类名;
        注意 投影查询得到的list集合每个对象是Object[] 数组/或object 对象
    7.聚集函数查询 count max min sum avg 等sql函数
        "select count(*) from User" //select +聚集函数+form+实体类名;
     
     
     
     

HQL多表查询

内链接  左外连接 右外连接

特有的查询:迫切内链接  迫切左外连接 (没有迫切右外连接)

    HQL多表查询
    1.内连接
    String hql = "from Customer c inner join c.setLinkMan" ;//用到都是本类中的属性值
    Query query = session.createQuery(hql);
    List<Objec[]> list = query.list();//返回的list集合的每个元素是Object[] 数组
     
    2.迫切内连接
    迫切内链接和内连接底层实现是一样的
    区别:内链接返回的是list的object[] 数组 ,但是迫切内连接返回的list 每个元素是对象
    String hql = "from Customer c inner join fetch c.setLinkMan"; //迫切内连接
     
    3.左外连接
    Sting hql = "from Customer c left outer join c.setLinkMan";
     
    4.迫切左外连接
    Sting hql = "from Customer c left outer join fetch c.setLinkMan";
    同上特性
    区别:左外链接返回的是list的object[] 数组 ,但是迫切左外连接返回的list 每个元素是对象
     
    5.右外连接 此处不写了同上
     

 

Crieator 对象没有sql hql 等对应的语句查询只有对应对象及方法作为条件进行查询

    Criteria --QBC查询
     
    //1.创建Criteria对象
    Criteria criteria = session.createCriteria(User.class);//参数位类的字节码对象
    //2.调用criteria对象方法
    List<User> list = criteria.list();
    //3.增强for循环查看
    for(User user : list){
        syso(user.getid()+ user.getname());
     
    }
     
    1.查询所有
    criteria.list();
    2.条件查询  使用criteria的add()方法 参数为对象Restriction(属性名,属性值)
        criteria.add(Restriction.eq("uid",1));
     
    3.模糊查询
    criteria.add(Restriction.like("uname","%白%");
     
    4.排序查询
    criteria.addOrder(Order.asc("uid")); //正序 Order.desc("uname") 倒序
     
    5.分页查询
    criteria.setFirstResult(0);//从0开始查找
    criteria.setMaxResult(3);//每页3条记录
    开始位置计算公式 : (当前页-1)*每页记录
     
    6.统计查询
    criteria.setProjection(Projection.rowcount);
    Object obj = criteria.uniqueResult();
    Long lobj = (Long)obj;
    int count = lobj.intValue();
    7.离线查询
    Detachedcriteria dc  = Detachedcriteria.forClass(User.class);
    Criteria c = dc.getExectableCriteria(session);
    List<User> list = c.list();

SQLQuery 查询

     SQLQuery 查询
    //创建SQLQuery对象
    SQLQuery sq = session.createSQLQuery(sql);//sql 为数据库sql 语句
    //执行对象方法返回结果
    List list = sq.list();//默认返回的list集合是数组形式 Object[]
    //遍历
    for(Object[] obj : list){
        syso(Arrays.toString(obj));
     
    }
     
    将结果转换成每个部分是对象
    sqlquery.addEntity(User.class);
    List<User> list = sqlquery.list();
    for(User u : list){
     
        syso(u);
    }

 


原文:https://blog.csdn.net/weixin_39209728/article/details/82944775

猜你喜欢

转载自www.cnblogs.com/gu-bin/p/10420449.html