hibernate

hibernate学习和介绍
1.对象关系映射O/R Mapping  Obejct/Relation Mapping
(1):orm:能在对象和关系型数据库两者间进行数据转换的机制  
Hibernate框架:能够实现ORM的框架
session 单线程 代表应用程序和持久化层之间的一次对话,封装了一个JDBC连接.
(2):O/R Mapping Frameworks
Hibernate
Toplink(Java对象关系可持续性体系结构,优秀的对象关系映射持久层解决方案)
Jdo(Java对象持久化的新的规范,也是一个用于存取某种数据仓库中的对象的标准化API)
Ibatis(mybatis)
JPA(JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。,而Hibernate是它的一种实现。

2.hibernate操作步骤
(1):导入jar包,idea则使用配置xml文件方式
<!-- 添加mysql驱动依赖 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.39</version>
    </dependency>
    <!-- 添加hibernate依赖包 -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.2.6.Final</version>
    </dependency>
    <!--集合工具类-->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-collections4</artifactId>
      <version>4.1</version>
    </dependency>
    <!-- jta-java transaction api -->
    <dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
    </dependency>
    <!-- slf4j-api 日志管理api-->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.25</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.25</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
      <version>1.7.25</version>
      <scope>test</scope>
    </dependency>
<!--注解hibernate-annotations -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-annotations</artifactId>
      <version>3.4.0.GA</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate/ejb3-persistence -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>ejb3-persistence</artifactId>
      <version>1.0.2.GA</version>
      <type>pom</type>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>5.2.17.Final</version>
  </dependency>

(2):建立hibernate配置文件 默认名字为: hibernate.cfg.xml
①:mysql版本
<?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>
    <!-- Database connection settings -->
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql:///dept?useUnicode=true&amp;characterEncoding=UTF-8</property><!--  注意:这里的dept是数据库名称  -->
    <property name="connection.username">root</property>
    <property name="connection.password">12345</property>
        <!-- JDBC connection pool (use the built-in) 连接池 -->
        <property name="connection.pool_size">1</property>
        <!--  数据库方言  -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!--  格式化sql语句  -->
        <property name="format_sql">true</property>
        <!-- 在控制台输出sql -->
        <property name="show_sql">true</property>
        <!-- 策略 -->
        <property name="hbm2ddl.auto">update</property>
        <!--使用的是本地事务(jdbc事务 本地事务:数据库只有一个)-->
        <property name="hibernate.current_session_context_class">thread</property>

        <!--添加映射文件-->
        <mapping class="com.test.po.Dept"/>
</session-factory>
</hibernate-configuration>
②:oracle版本
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <!-- 这里的orcl是数据库名称 -->
        <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
        
        <property name="connection.username">scott</property>
        <property name="connection.password">tiger</property>

        <!-- JDBC connection pool (use the built-in) 连接池 -->
        <!-- <property name="connection.pool_size">1</property> -->

        <!-- SQL dialect 方言 -->
        <property name="dialect">org.hibernate.dialect.OracleDialect</property>

        <!-- Enable Hibernate's automatic session context management 线程 单线程 -->
        <!-- 在代码中获取session有两种方式,其中一种需要添加该配置 -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache -->
        <!-- 配置缓存 -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <!-- 在控制台输出sql -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <!-- 策略 -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 注解mapping文件 -->
        <!--将映射文件加入到配置文件hibernate.cfg.xml中.-->
        <!-- <mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml" /> -->

    </session-factory>

</hibernate-configuration>

(3):创建po层
package com.hibernate.pojo;

public class Dept {

      private int deptno;
      private  String  dname;
      private  String  loc;
    public int getDeptno() {
        return deptno;
    }
    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }
    public String getDname() {
        return dname;
    }
    public void setDname(String dname) {
        this.dname = dname;
    }
    public String getLoc() {
        return loc;
    }
    public void setLoc(String loc) {
        this.loc = loc;
    }
    @Override
    public String toString() {
        return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
    }    
}
(4):创建dept类的映射文件 Dept.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hibernate.pojo">

<class name="Dept" table="Dept" >
  <id  name="deptno" column="deptno" >//name对应po层里面的类,column数据库里面的字段
  <generator class="native"></generator>//id让他自动生成,添加数据的时候自动加上去
  </id>
  <property name="dname" column="dname" />
  <property name="loc" />//如果javabing里和数据库里名字一样,colume可以不配置

</class>
</hibernate-mapping>

(5):创建工具类
package com.hibernate.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;//不会自动帮忙导包

public class HibernateUtil {
//静态方法帮我们创建一个session工厂
//全局静态 从一开始加载就会存在,而且不会改变,这样写是一种优化方式,只需要创建一次
//final关键字,常量不可改变
    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            //这里出现问题的可能性比较大,比如配置文件出问题等
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);//这个异常叫初始化异常
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

也可以像下面这样创建:
package com.test.util;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.SessionFactory;

public class HibernateUtil {
    private static SessionFactory sessionFactory;
    /**
     *
     * @return Session
     */
    public static Session getSession(){
        return getSessionFactory().getCurrentSession();
    }
    /**
     * SessionFactory是重量级的
     * 最好做成单例模式
     * @return SessionFactory
     */
    public static SessionFactory getSessionFactory(){
        //保证SessionFactory为单例
        if (sessionFactory == null ||sessionFactory.isClosed()) {
            sessionFactory = new Configuration().configure().buildSessionFactory();
        }
        return sessionFactory;
    }
}

(6): 编写测试类
package com.hibernate.test;
import org.hibernate.Session;
import com.hibernate.pojo.Dept;
import com.hibernate.util.HibernateUtil;
public class HibernateTest {
    public static void main(String[] args) {
        Dept dept = new Dept();

        dept.setDname("XX部");
        dept.setLoc("一群XX");
        saveDept(dept);
        HibernateUtil.getSessionFactory().close();
    }
    private static void saveDept(Dept dept) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        // 开启事务
        session.beginTransaction();
        session.save(dept);
        // 提交事务
        session.getTransaction().commit();
    }
}


3.hibernate注意事项:
(1).Hibernate.cfg.xml:hbm2ddl.auto(用的比较多是create)
a)Create 自动在数据库创建表 
b)Update 根据实体类更新表结构
c)create-drop关闭SessionFactory 会把数据库创建好的表给删掉
d)validate  对数据操作之前会检查表的结构是否与配置文件是否匹配
(2):先建表后建类


4:使用注解方式实现上面的案例
pom.xml里面需要将注解部分注释
不再需要类的Dept.hbm.xml映射文件
修改类:
package com.test.po;
import javax.persistence.*;
@Entity//表示实体类 注解的是实体类 用javax哪一个
@Table(name="dep")//类名与表名不一致 用javax哪一个 dept2表名
public class Dept {
    private int deptno;
    private String dname;
    private String loc;
    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }
    @Override
    public int hashCode() {
        return super.hashCode();
    }
    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                ", loc='" + loc + '\'' +
                '}';
    }
    @Id //表示主键
    @Column(name = "id")//属性名与表中主键的列名不一致  一致可以不写
    @GeneratedValue(strategy = GenerationType.SEQUENCE)//主键生成策略 自动生成
    public int getDeptno() {
        return deptno;
    }
    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }
    @Column(name = "dname")//非主键 如果 属性名和列名一致 可以不写
    public String getDname() {
        return dname;
    }
    public void setDname(String dname) {
        this.dname = dname;
    }
    public String getLoc() {
        return loc;
    }
    public void setLoc(String loc) {
        this.loc = loc;
    }
}


修改hibernate配置文件的mapping
<!--添加映射文件-->
        <mapping class="com.test.po.Dept"/>

5:核心开发接口介绍·
Hibernate 核心接口 三种对象状态 四种操作方法

a)Configuration
i.AnnotationConfiguration
ii.进行配置信息管理
iii.用来产生SessionFactory
iv.可以在configure方法在指定hibernate配置文件
v.只需要关注一个方法:buildSessionFactory
b)SessionFactory
i.用来产生和管理session
ii.通常情况下每个应用只需要一个SessionFactory
iii.除非要访问多个数据库的情况
iv.关注两个方法即可:openSesion  getCurrentSession
Opensession每次都是新的
getCurrentSession从上下文找,如果有,用旧的,如果没有,建新的
 1. 用途,界定事务边界
2. 事务提交自动close
3. 上下文配置可参见xml文件中
                           <property name="current_session_context_classs">thread</property>

c)Session
管理一个数据库的任务单元(简单说就是增删 改 查)
方法
a)Save()
b)Delete()
c)Update()
d)SaveOrUpdate()
save()方法很显然是执行保存操作的,如果是对一个new出来的对象进行保存,自然要使用这个方法了,数据库中没有这个对象。
update()如果是对一个已经存在的游离对象进行更新那么肯定是要使用update()方法了,数据中有这个对象。
saveOrUpdate()这个方法是更新或者插入,有主键就执行更新,如果没有主键就执行插入。
区别:对于一个从游离状态到瞬态的对象(对于一个从数据库中取出来又被删除的对象),这个对象本身是有主键的,但是因为被删除了,所以这个时候因为数据库中已经没有了这条记录了。不过它还有主键存在,所以这个时候不可以使用update()或者是saveOrUpdate(),因为update()方法是认为数据库中肯定有这条记录的,而saveOrUpdate的执行过程就是先查看这个对象是不是有主键,有主键那么就执行update()方法,没有主键就执行save()方法,因此结果跟调用了update()方法的效果是一样的,结果就会出错,因为这个对象已经被删除了,数据库中已经没有这条记录了,只是它还有主键而已(仅仅是存在于内存中),因此这个时候要执行的是save()方法

e)Load
f)Get
Get与load的区别(面试重点,原理)
1. 不存在对应记录时表现不一样
2. load返回的是代理对象,等到真正用到对象的内容时才发出sql语句
3. get直接从数据库加载,不会延迟
get方法首先查询session缓存,没有的话直接发送sql查询数据库,一定要获取到真实的数据,否则返回null,并不适用二级缓存;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,就抛异常(所谓延迟加载也称为懒加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。)
(代理实际就是空的对象 并没有去数据库查询得到的 我们叫代理对象,如果 去数据库查询了 返回到了这个对象 我们叫实体对象 就是这个对象真实存在)
g)Clear方法
无论是load还是get 都会首先查找缓存(一级缓存),如果没有,才会从数据库查找,调用clear()方法可以强制清除session缓存
Session.Commit() 这个方法它自动调用了close()和flush()方法
h) 调用flush()可以强制从内存到数据库的同步
三种对象状态图

i)三种状态的区别
区分方法:              有没有id,  数据库中有没有,session缓存中有没有
Trasient(临时状态):    没有id,    数据库中没有,    缓存没有
Persistent(持久化状态):有id,         数据库有,       缓存有
Detached(游离状态):   有id,       数据库有,        缓存没有
Configuration configuration=new AnnotationConfiguration();
        Configuration configuration2=configuration.configure();
        SessionFactory sFactory=configuration2.buildSessionFactory();
        Session session=sFactory.getCurrentSession();
        session.beginTransaction();
    //临时状态
//此时的people为一个Transient对象,因为没有与任何数据库的任何记录相关联.
        People people=new People();
        people.setName("女娲");
        people.setSex(Gender.male);

        //持久状态 缓存区中有记录 数据库中也有记录
        session.save(people);
        session.getTransaction().commit();

        //游离状态  缓存无(session关闭了无人管理了所以称为游离):
        System.out.println(people.getId());

save方法完成之后,session将对象引用放在session缓存区中,
 有一个hasMap引用,里面有一系列key和对应的vaule指向这个应用的对象。
 比如上面的save(t)完成之后,会 有一个id的key,然后value指向数据库中那个对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值