Hibernate的学习笔记

Hibernate的学习笔记
一.Hibernate是什么?
    1. Hibernate是一个框架(framework)
       2.Hibernate是一个o(object)r(relation)m(mapping)框架
       3.Hibernate处于项目的持久层(所以有人将其称为持久层框架)
       4.Hibernate实际上就是将jdbc进行了轻量级的封装
       5.Hibernate的基础还是java的反射机制
       6.Hibernate可以用在j2ee和j2se项目中,但是Struts是web层框架,所以他只能用在j2ee项目中

      总结:Hibernate是对jdbc进行轻量级封装的orm框架,处于项目的持久层位置。

二.为什么需要Hibernate?


三.Hibernate的三种开发方式:
1.由Domain object->mapping->db。(官方推荐)
2.由db开始,用工具生成mapping和Domain object。(使用较多)(建议domain类的首字母大写和表的名字对应 )
3.由映射文件开始。

什么是pojo?
 在使用Hibernate的时候,要求数据局的某张表相互映射的那个java类,是一个pojo类,一般放在com.xxx.domain包下,pojo类翻译过来就是:简繁的就java对象(plain ordinary java objects)实际上就是普通的Javabeans,使用pojo名称是为了避免个ejb混淆起来。一个pojo类应该具有:
    1.有一个主键属性,用于唯一标示该对象。(这就是为什么Hibernate的设计者建议要映射的表需要一个主键)
    2.有其他的属性
    3.有对各个属性操作的get/set方法。
    4.属性一般是private修饰。
    5.一定有一个无参的构造函数(用于Hibernate框架的反射用)。

Hibernate的配置文件如下:
    
    
<?xml version="1.0" encoding="UTF-8"?>
<!-- 映射文件需要一个dtd文件  来指定格式 -->
<!DOCTYPE hibernate-mapping PUBLIC
          "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.liheng.domain">
    <class name = "Employee" table = "employee">
        <!-- id元素用于指定主键属性 -->
        <id name = "id" column="id" type="java.lang.Integer">
            <!-- 该元素用于指定主键生成策略 hilo native increment sequence uuid-->
        <!--     <generator class="sequence">
                <param name="sequence">id</param>
            </generator> -->
            <generator class="increment"></generator>
        </id>
        
        <!-- 对其他属性进行配置 -->
        <property name="name" type="java.lang.String">
            <column name="name" not-null="false"></column>
        </property>
        <property name="email" type="java.lang.String">
            <column name="email" not-null="false"/>
        </property>
        <property name="hiredate" type="java.util.Date">
            <column name="hiredate" not-null="false"></column>
        </property>
    </class>
</hibernate-mapping>  

Hibernate的增删改:
    
    
public static void delEmp() {
        //删除
        Session session = MySessionFactory.getSessionFactory().openSession();
        Transaction ts = session.beginTransaction();
        //删除1.现获取该雇员 然后删除
        Employee emp = (Employee) session.load(Employee.class, 1);
        session.delete(emp);
        ts.commit();
        session.close();
    }
    public static void updateEmp() {
        //修改用户
        //创建configuaration
        //创建会话工厂  这是一个重量级的对象 应当保证sessionFactory是单态的
        Session session = MySessionFactory.getSessionFactory().openSession();
        Transaction ts = session.beginTransaction();
        //修改用户1 获取要修改的用户 , 2 修改
        //load是通过主键属性,获取该对象实例    与表的记录对应
        Employee emp = (Employee) session.load(Employee.class, 1);
        emp.setName("zhangsan");//update
        ts.commit();
        session.close();
    }
    
    public static void addEmployee() {
        //我么使用Hibernate完成srud操作  这里我们只键对象,不见表
        //现在不使用service 直接测试
        //1.创建configration 该对象用来读取Hibernate.cfg.xml文件,并完成初始化
        Configuration configuration = new Configuration().configure();
        //2.创建sessionfactory 这是一个会话工厂 是一个重量级对象
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        //创建Session 相当于jdbc的connection
        Session session = sessionFactory.openSession();
        
        //对于Hibernate来说要求程序员  在进行 增加 删除 修改 时候用事务提交
        Transaction transaction = session.beginTransaction();
        //添加一个雇员
        Employee employee = new Employee();
        employee.setName("liheng");
        employee.setEmail("liheng216.sina.com");
        employee.setHiredate(new Date());
        
        //insert...保存
        session.save(employee);//对应insert into 。。。
        transaction.commit();
        session.close();
    }  
Hibernate的核心类和接口


1.configuration类
它的用处是:
  • 读取Hibernate.cfg.xml文件
  • 管理对象关系映射文件<mapping resource ="">
  • 加载Hibernate的驱动,url,用户。。。
  • 管理配置信息    
2.Hibernate.cfg.xml配置文件
3.对象关系映射文件
4.sessionFactory(会话工厂)
  • 缓存sql语句和某些数据(称为session级缓存)
  • 是一份重量级的类,因此,我们需要保证一个数据库有一个SessionFactory

  • 通过SessionFactory接口可以获得Session(会话)实例
这里讨论一个 SessionFactory接口可以获得Session的两个方法,openSession()和getCurrentSession();
    1. openSession()是获取一个新的session
   
   
    Session s1 = MySessionFactory.getSessionFactory().openSession();
        Session s2 = MySessionFactory.getSessionFactory().openSession();

   
   
        
        //输出hashcode
        System.out.println("s1 =" + s1.hashCode() +" "+"s2=" + s2.hashCode() );
s1 =7858936 s2=14900151  

    2. getCurrentSession() 获取和当前线程绑定的session,换言之,在同一个线程中,我们获取的session是同一个session,这样可以利于事务处理。如果希望使用 getCurrentSession()  需要配置Hibernate.cfg.xml中配置
   
   
   
 Session s1 = MySessionFactory.getSessionFactory().getCurrentSession();
        Session s2 = MySessionFactory.getSessionFactory().getCurrentSession();
        
        //输出hashcode
        System.out.println("s1 =" + s1.hashCode() +" "+"s2=" + s2.hashCode() );
s1 =1673653 s2=1673653  

    3如何选择:
    原则:
  •     如果在同一线程中,保证使用同一个Session,则使用getCurrentSession()
  • 如果在一个线程中需要使用不同的Session,则使用openSession()
    4.两种方式的不同

5.如果是getCurrentSession()获取session,进行查询需要事务提交。
6.jta

5.如果是getCurrentSession()获取session,进行查询需要事务提交。
6.jta


7.Session(会话)接口
  •     session一个实例代表与数据库的一次操作(当然一次操作可以是crud组合)
  • session实例同过sessionFactory获取,用完需要关闭
  • session是线程不同步的(不安全),因此要保证在同一线程中使用,可以用getCurrentSession()
  • Session可以看做是持久化管理器,它是与持久化操作的接口




    4.通过修改配置文件我们可以修改懒加载< class name = "Employee" lazy="true" table = "employee" >

Hibernate的缓存的介绍:
分两级   主要作用:减少用户对数据库的操作

query接口:
通过query接口我们可以完成更为复杂的操作
     
     
Session session = HibernateUtil.getCurrentSession();
                Transaction ts = null;
                try {
                    ts = session.beginTransaction();
                    //获取一个query借口引用 这里的Employee不是表而是domain类名 where后面的是类的成员变量
                    Query query = session.createQuery("from Employee where id = 2");
                    //通过list方法获取结果
                    //原来使用jdbc二次封装的工作就没有了
                    List<Employee> list = query.list();
                    for (Employee e :list) {
                        System.err.println(e.getName());
                    }
                    
                    ts.commit();
                } catch (Exception e) {
                    if (ts !=null) {
                        ts.rollback();
                    }
                    throw new RuntimeException(e.getMessage());
                }finally{
                    //关闭session
                    if (session != null && session.isOpen()) {
                        session.close();
                    }
                }  



HQL(Hibernate query language)语句
模拟创建三张表:
--建立学生表
create table student
(sid number primary key , --这是学生的学号
sname varchar2(45) not null, --学生姓名
ssex  char(2) not null,--性别
sdept varchar2(10) not null, --所在系
sage  number(3) ,--年龄
saddress varchar2(45) --住址
)
create table course
(
cid number primary key ,--这是课程号
cname varchar2(50) not null,--课程名
ccredit number(3) --课程学分
)
--建立选课表
create table studCourse
(
stuCourseId number primary key ,--这是一个自增的,表示一次选课
sid number  references student(sid),--学生号
cid number references course(cid),--课程号
grade number not null--成绩
)
Hibernate的设计者在我们设计表的时候,应当每张表都有一个主键,而且该主键最好不包含任何的业务逻辑。
使用Hibernate工具,自动生成domain和映射文件,如果我们的表有主外键的关系应当先映射主表再映射从表。

Hibernate对象的三种关系:
1.one-to-one:人和身份证的关系;
2.one-to-many:部门和员工的关系;
3.many-to-one:员工和部门;
4.many-to-many:学生和老师;


Hibernate对象的三种状态:
瞬时态:不处于session的管理之下,在数据库中没有对应的记录。超过作用域就会被jvm回收,一般是new出来的并且与session没有关联的对象。
持久态:在session的管理之下,在数据库中有对应的记录,相关联的session没有关闭,事务没有提交。持久对象的状态发生变化,在事务提交时会影响到数据库(Hibernate能检测到)。
脱管态/游离态:没有处于session的管理之下,在数据库中有对应的记录。托管状态发生改变,Hibernate不能检测到。

懒加载:
简述:当我们查询一个对象的时候,在默认情况下返回的只是该对象的普通属性,当用户使用对象属性时,才会向数据库再一次发出查询,这种现象我们称之为懒(lazy)加载现象。
三种解决方法:
1.显式初始化 Hibernate  initized(代理对象)
2.修改对象关系文件 lazy 改写 lazy = false
3.通过过滤器(web项目)openSessionInView
一个内部留言本的项目

在jsp页面中获取当前的项目名可以:
<%= this.getServletContext().getContextPath()%>
通过标签:${pageContext.request.contextPath}

Hibernate的缓存
为什么需要缓存?


一级缓存(session级缓存)
1.什么操作会向一级缓存里面放进东西?

2.是么操作会从一级缓存取数据?
    get/load/list
    get/load会首先从一级缓存中取。如果没有,再有 不同的操作【get 会立即向数据库发请求,而load会返回一个代理对象,直到用户真的去使用数据,才会向数据库发请求】


3.一级缓存不需要配置,就可以使用,它本身没有保护机制,所以我们程序员要考虑这个问题,
二级缓存(sessionFactory级缓存):
为什么需要二级缓存?
因为一级缓存有限,还有一级缓存的生命周期很短,所以我们需要二级缓存来弥补这个问题。
1.二级缓存需要配置
2.二级缓存需要交给第三方处理
3.二级缓存的对象可能放到内存中,也可能放到磁盘上。


    Hibernate最佳实践:
    对于数据量大,性能要求高的系统,不太使用Hibernate
    主要用于事务操作比较多的项目。(oa/某个行业软件【石油、税务、crm、财务系统】)



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半路笙歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值