hibernate的基本使用

一.Java3大框架在三层结构中的使用

- web层(视图层)      :struts2
- service层(服务层)  :spring
- dao层(数据库操作层) :hibernate

二.hibernate概述

1.hibernate框架概述

> hibernate是Javaee中3层架构的dao层,也就是数据持久化层.
> hibernate是对jdbc进行的封装,简化数据库的操作
> hibernate是开源的,轻量级的框架

2.hibernate的orm思想(object,relational,mapping),对象关系映射

> hibernate的orm思想是将实体类和数据库表进行一一对应,即实体类属性和数据库字段名字一样.
> 操作的时候,不需要操作数据库,而是操作实体类对象.

三.hibernate入门

1.创建一个hibernate项目的步骤

> 导入jar包
> 创建实体类
> 创建数据库表(hibernate会自动创建)
> 实现映射关系创建配置文件,配置文件的方式

创建位置一般在实体类所在的包中
名称一采用实体类名.hbm.xml
约束文件
“-//Hibernate/Hibernate Mapping DTD 3.0//EN”
“http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd”>

<hibernate-mapping>
    <!-- 配置实体类和表的对应 -->
    <class name="com.hibernate.entry.User" table="user">
        <!-- 配置实体类的id属性,对应于表的id,要求唯一才行 -->
        <id type="int" name="id" column="id">
            <!-- 设置主键自动增长,有很多值 -->
            <generator class="native"></generator>
        </id>
       <!-- 其他属性的配置 -->
       <property name="userName" column="userName"></property>
       <property name="password" column="password"></property>
    </class>

</hibernate-mapping>
>核心配置文件

位置和名称固定:位置在src下,名字叫hibernate.cfg.xml
约束文件
“-//Hibernate/Hibernate Configuration DTD 3.0//EN”
“http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd”>

<hibernate-configuration>
    <session-factory>
        <!-- 1.配置数据库信息,必须 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>        
        <property name="hibernate.connection.username">root</property>  
        <property name="hibernate.connection.password"></property>  

        <!-- 2.配置hibernate信息,可选 -->
        <!-- 执行的时候输出底层的SQL语句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 格式化SQL语句 -->
        <property name="hibernate.format_sql">true</property>
        <!-- hibernate帮助自动创建表 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- 配置数据库的方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- 3.把映射文件都放到本核心配置文件中,因为hibernate只会加载核心配置文件 -->
        <mapping resource="com/hibernate/entry/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>
>测试
测试的7个步骤
//1.加载hibernate核心配置文件
//2.创建sessionFactory对象,在此过程中,根据映射关系,创建表
//3.使用sessionFactory创建session对象
//4.开启事务
//5.写具体的curd操作,添加的操作
//6.提交事务
//7.关闭资源
    public static void myTest() {
        //1.加载hibernate核心配置文件
        Configuration cfg=new Configuration();
        cfg.configure();
        //2.创建sessionFactory对象,在此过程中,根据映射关系,创建表
        SessionFactory sessionFactory= cfg.buildSessionFactory();

        //3.使用sessionFactory创建session对象
        Session session= sessionFactory.openSession();

        //4.开启事务
        Transaction tx = session.beginTransaction();

        //5.写具体的curd操作,添加的操作
        User user=new User();
        user.setUserName("申");
        user.setPassword("123456");
        System.out.println(user.getUserName());
        session.save(user);

        //6.提交事务
        tx.commit();

        //7.关闭资源
        session.close();
        sessionFactory.close();
    }
执行结果

数据库表创建成功,数据插入成功,小问题是出现了中文问题

四.hibernate深入

1.hibernate的主键生成策略

<!-- 配置实体类的id属性,对应于表的id,要求唯一才行 -->
        <id type="int" name="id" column="id">
            <!-- 设置主键自动增长,有很多值 -->
            <generator class="native"></generator>
        </id>
-----------------------------------------------------------------------
生成策略有很多的值:
1.native : 自动选择适合于相应的数据库的主键自动增长方式
2.uuid   : 自动生成uuid,32位的16进制字符串

2.hibernate的curd操作

  • 增加,调用session.save(user);
//5.写具体的curd操作,添加的操作
        User user=new User();
        user.setUserName("zhu");
        user.setPassword("123456");
        System.out.println(user.getUserName());
        session.save(user);
  • 删除,session.delete(user);
        User user = session.get(User.class, 2);
        session.delete(user);
  • 修改,调用session.update(user);
//5更新操作
        User user = session.get(User.class,2);
        user.setUserName("shenyuchao");
        session.update(user);
        System.out.println(user.getId()+":"+user.getUserName()+":"+user.getPassword());
  • 查询,调用session.get(User.class,1);
//5 查询事件
        User user = session.get(User.class,1);
        System.out.println(user.getId()+":"+user.getUserName()+":"+user.getPassword());

3.实体类的状态

  • 瞬时态 : 实体类没有id,也跟session没有关联
  • 持久态 : 实体类有id,也跟session有关联
  • 托管态 : 实体类有id,跟session没有关联

当在以上3中状态中调用session.saveOrUpdate();方法的时候,
瞬时态会执行save,持久态和托管态会执行update

4.hibernate缓存

hibernate的一级缓存
(1)hibernate一级缓存默认打开的
(2)hibernate一级缓存使用的范围是session内,当session关闭就没有了缓存
(3)hibernate一级缓存中的数据必须是持久态的数据
---------------------------------------------------------------------
操作的数据会被缓存到内存中,当进行修改的时候,会操作内存中的数据,然后事务提交的时候,如果数据需要修改,就会更新数据库,如果数据不需要修改就不会更新数据库.

5.hibernate绑定session

(1)在核心配置文件中配置才能使用
<property name="hibernate.current_session_context_class">thread</property>
(2)在程序中调用方法
sessionFactory.getCurrentSession();
(3)curd操作结束则本地线程结束,那么这个session也结束了,不需要手动关闭

6.hibernate的多种查询

  • Query对象
使用这个对象不需要写sql语句,但是需要写hql(hibernate query language)语句
SQL换个hql的区别
(1)使用SQL操作的是数据库的表和表的字段
(2)使用hql操作的是实体类和实体类的属性
Query对象的使用
(1)查询所有: from 实体类名称
    public static void   query() {
        SessionFactory sessionFactory=null;
        Session session=null;
        Transaction tx=null;
        try {
            sessionFactory =Util.getSessionFactory();
            session =Util.getSession();
            tx=session.beginTransaction();

            //Query对象的使用
            Query query=session.createQuery("from User");
            java.util.List<User> list= query.list();
            for (User user:list) {
                System.out.println(user);
            }

            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
//          session.close();
            sessionFactory.close();
        }
    }
  • Criteria对象
Criteria对象不需要写查询语句,直接调用方法即可
    public static void   criteria() {
        SessionFactory sessionFactory=null;
        Session session=null;
        Transaction tx=null;
        try {
            sessionFactory =Util.getSessionFactory();
            session =Util.getSession();
            tx=session.beginTransaction();

            //**Criteria的使用方法**
            Criteria criteria = session.createCriteria(User.class);
            List<User> users= criteria.list();
            for (User user:users) {
                System.out.println(user);
            }
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
//          session.close();
            sessionFactory.close();
        }
    }
  • SQLQuery对象
SQLQuery执行的是底层的SQL语句
    public static void   sqlQuery() {
        SessionFactory sessionFactory=null;
        Session session=null;
        Transaction tx=null;
        try {
            sessionFactory =Util.getSessionFactory();
            session =Util.getSession();
            tx=session.beginTransaction();

            //SQLQuery的使用方法
            SQLQuery sqlQuery=session.createSQLQuery("select * from user");
            sqlQuery.addEntity(User.class);
            List<User> users=sqlQuery.list();
            for (User user:users) {
                System.out.println(user);
            }
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
//          session.close();
            sessionFactory.close();
        }
    }

7.hibernate的表与表关系的操作

1.表关系
  • 一对多 : 在多的那张表里有一个字段作为外键,这个外键指向一的那张表的主键

  • 多对多 : 生成第三张表,这个表至少包含其他两个表的主键

2.hibernate中1中的思想的实现
  • 一对多实现

(1)建立实体类

代码类似,不再演示

(2)让实体类中两方能够互相表示

在一的一方(客户),使用set集合保存多的一方,并建立getset方法:
private Set<LinkMan> setLinkMans=new HashSet<LinkMan>();
在多的一方,使用一的实体对象来表示,并建立getset方法:
private Customer customer;

(3)配置文件中做配置,并建立映射关系

在一的一方,配置如下:
 <!--name:就是实体类中set的名字-->
 <set name="setLinkMans">
    <!-- 配置外键,外键是值就是外键的名称 -->
    <key column="clid"></key>
    <!-- 配置的是联系的那个实体类全路径 -->
    <one-to-many class="com.hibernate.entry.LinkMan"/>
 </set>
在多的一方,配置如下:
<!-- 配置和customer实体类相联系 ,column是外键名称,两个配置文件中的外键名称一致-->
       <many-to-one name="customer" class="com.hibernate.entry.Customer" column="clid"></many-to-one>
  • 多对多实现
实现步骤与上面相同,只是配置不同
       <!--name指实体类中set集合名称, table指第三张表的名称 -->
       <set name="setRoles" table="user_role">
            <!-- column指当前映射文件在第三张表中的外键名称 -->
            <key column="userid"></key>
            <!-- class对应另一个多的全路径,column指这个多在第三张表的外键名称 -->
            <many-to-many class="com.hibernate.many2many.Role" column="roleid"></many-to-many>
       </set>
-------------------------------------------------------------------------------
 <set name="setMUsers" table="user_role">
            <key column="roleid"></key>
            <many-to-many class="com.hibernate.many2many.MUser" column="userid"></many-to-many>
       </set>
    </class>
hibernate级联操作
  • 一对多级联

(1)级联保存

    /*
     * 这是一种比较麻烦的方法,
     * 建立一的实体类,建立多的实体类,分别表示对方,最后分别保存
     */
    public static void save1() {
        SessionFactory sessionFactory=null;
        Session session=null;
        Transaction tx=null;
        try {
            sessionFactory =Util.getSessionFactory();
            session =Util.getSession();
            tx=session.beginTransaction();

        Customer customer=new Customer();
        customer.setCname("shen");
        customer.setCpassword("123456");

        LinkMan linkMan=new LinkMan();
        linkMan.setLname("zhu");
        linkMan.setLpassword("123456");

        //互相表示对方
        customer.getSetLinkMans().add(linkMan);
        linkMan.setCustomer(customer);

        //分别保存
        session.save(customer);
        session.save(linkMan);

            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
//          session.close();
            sessionFactory.close();
        }
    }

/*
     * 这是一种比较简单的写法,需要配置,底层实现还是一样的思想
*/
--------------------------------------------------------------
配置:在一的一方的配置文件中加入级联(cascade="save-update"):
<set name="setLinkMans" cascade="save-update">
--------------------------------------------------------------
            Customer customer=new Customer();
            customer.setCname("chao");
            customer.setCpassword("123456");

            LinkMan linkMan=new LinkMan();
            linkMan.setLname("ping");
            linkMan.setLpassword("123456");

            //不用再互相保存对方了,只需要将linkman添加到set中去
            customer.getSetLinkMans().add(linkMan);

            //不用分别保存了,只需要保存customer
            session.save(customer);

(2)级联删除

/*
     * 配置了之后,进行级联删除
     * 查询然后直接调用delete方法
     */
----------------------------------------------------------------
配置在一的一方: 
<set name="setLinkMans" cascade="save-update,delete">
----------------------------------------------------------------

删除代码:           
Customer customer=session.get(Customer.class, 2);
session.delete(customer);

(3)级联修改

需求就是把某一个客户的联系人变成另一个客户的联系人

该修改方式有一个弊端,因为hibernate是对外键双向维护的,就造成2次数据库对多的一方的更新,解决的方式是:让一的一方放弃维护外键

<set name="setLinkMans" cascade="save-update,delete" inverse="true">
不需要配置,思想如下:
1.获取目标客户实体对象,
2.获取目标联系人实体对象,
3.将联系人添加到客户,再将客户添加到联系人中
因为这2个实体对象都是持久态的数据,不需要调用session的方法,提交后就会更新数据库
  • 多对多级联

(1)多对多级联保存,类似于一对多操作

(2)多对多级联删除,类似于一对多操作


* 多对多维护第三张表 *

对于多对多的操作思想是:将两个多方分别操作,剩下的就是操作第三张表,就能完成功能.比如:
User user=session.get(User.class,2);
Role role=session.get(Role.class,3);
//增加关系
user.getSetRoles().add(role);
//删除关系
user.getSetRoles().remove(role);

五.hibernate的查询

1.对象导航查询,就是查询到一个某一个客户的所有联系人

User user=session.get(User.class,1);
//只需要得到set集合就行,得到的set集合就是想要的结果
Set<LinkMan> linkMans=user.getLinkmans();

2.OID查询,根据id查询方式

根据id查询,上面写过,不写了

3.hql查询,就是Query方式

4.QBC查询,就是Criteria方式

5.本地sql查询,就是SQLQuery方式

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值