01-Hibernate、环境搭建、配置、API、CRUD

1.1、Hibernate框架学习路线
  Hibernate的入门(Hibernate的环境搭建、Hibernate的API、Hibernate的CRUD)
  Hibernate的一级缓存、其他的API
  Hibernate的一对多配置、Hibernate的多对多的配置
  Hibernate的查询方式、抓取策略

1.2、CRM案例
1.2.1、CRM概述
1.2.1.1、什么是CRM
1.2.1.2、CRM有哪些模块

1.3、Hibernate概述
1.3.1、框架概述

1.3.2、EE的三层架构

1.3.2.1、EE的景点三层架构

1.3.3、Hibernate概述
1.3.3.1、什么是Hibernate

1.3.3.2、ORM

1.4、Hibernate入门
1.4.1、Hibernate入门
1.4.1.1、搭建开发环境

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.itheima</groupId>
  <artifactId>hibernate_day01</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>antlr</groupId>
      <artifactId>antlr</artifactId>
      <version>2.7.7</version>
    </dependency>

    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1.1</version>
    </dependency>

    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>

    <dependency>
      <groupId>org.apache.geronimo.specs</groupId>
      <artifactId>geronimo-jta_1.1_spec</artifactId>
      <version>1.1.1</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-c3p0</artifactId>
      <version>5.0.7.Final</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate.common</groupId>
      <artifactId>hibernate-commons-annotations</artifactId>
      <version>5.0.1.Final</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.0.7.Final</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate.javax.persistence</groupId>
      <artifactId>hibernate-jpa-2.1-api</artifactId>
      <version>1.0.0.Final</version>
    </dependency>

    <dependency>
      <groupId>org.jboss</groupId>
      <artifactId>jandex</artifactId>
      <version>2.0.0.Final</version>
    </dependency>

    <dependency>
      <groupId>org.javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.18.1-GA</version>
    </dependency>

    <dependency>
      <groupId>org.jboss.logging</groupId>
      <artifactId>jboss-logging</artifactId>
      <version>3.3.0.Final</version>
    </dependency>

    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
    </dependency>

    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>mchange-commons-java</artifactId>
      <version>0.2.3.4</version>
    </dependency>
    
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>
   
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
    </dependency>

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.1</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.2</version>
    </dependency>
  </dependencies>
  
</project>
pom.xml

1.4.1.2、创建表

CREATE TABLE `cst_customer` (
  `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
  `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
  `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
  `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
  `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
  `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
  `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
  PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Customer表

1.4.1.3、创建实体类

1.4.1.4、创建映射配置文件
映射需要通过XML的配置文件来完成,这个配置文件可以任意命名。尽量统一命名规范(类名.hbm.xml)
约束文件位置:

>xsd > 

<?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">
<hibernate-mapping>
  <!-- 建立类与表的映射 -->
  <class name="com.itheima.hibernate.demo01.Customer" table="cst_customer">
    <!-- 建立类中的属性与表中的主键对应 -->
    <id name="cust_id" column="cust_id" >
      <generator class="native"/>
    </id>

    <!-- 建立类中的普通的属性和表的字段的对应 -->
    <property name="cust_name" column="cust_name" length="32" />
    <property name="cust_source" column="cust_source" length="32"/>
    <property name="cust_industry" column="cust_industry"/>
    <property name="cust_level" column="cust_level"/>
    <property name="cust_phone" column="cust_phone"/>
    <property name="cust_mobile" column="cust_mobile"/>
  </class>
</hibernate-mapping>
Customer.hbm.xml

1.4.1.5、创建Hibernate核心配置文件

<?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>
    <!-- 连接数据库的基本参数 -->
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql:///hibernate_day01</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">root</property>
    <!-- 配置Hibernate的方言 -->
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

    <!-- 可选配置================ -->
    <!-- 打印SQL -->
    <property name="hibernate.show_sql">true</property>
    <!-- 格式化SQL -->
    <property name="hibernate.format_sql">true</property>
    <!-- 自动创建表 -->
    <property name="hibernate.hbm2ddl.auto">update</property>

    <!-- 配置C3P0连接池 -->
    <property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
    <!--在连接池中可用的数据库连接的最少数目 -->
    <property name="c3p0.min_size">5</property>
    <!--在连接池中所有数据库连接的最大数目  -->
    <property name="c3p0.max_size">20</property>
    <!--设定数据库连接的过期时间,以秒为单位,
    如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
    <property name="c3p0.timeout">120</property>
    <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
    <property name="c3p0.idle_test_period">3000</property>

    <mapping resource="com/itheima/hibernate/demo01/Customer.hbm.xml"/>
  </session-factory>
</hibernate-configuration>
hibernate.cfg.xml
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">3</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">30</property>
<!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
<property name="acquireRetryDelay">1000</property>
<!--连接关闭时默认将所有未提交的操作回滚。Default: false -->
<property name="autoCommitOnClose">false</property>
<!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么
属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试
使用。Default: null-->
<property name="automaticTestTable">Test</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->
<property name="breakAfterAcquireFailure">false</property>
<!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出
SQLException,如设为0则无限期等待。单位毫秒。Default: 0 -->
<property name="checkoutTimeout">100</property>
<!--通过实现ConnectionTester或QueryConnectionTester的类来测试连接。类名需制定全路径。
Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->
<property name="connectionTesterClassName"></property>
<!--指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可
Default: null-->
<property name="factoryClassLocation">null</property>
<!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs.
(文档原文)作者强烈建议不使用的一个属性-->
<property name="forceIgnoreUnresolvedTransactions">false</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">60</property>
<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">3</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">60</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">15</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
<property name="maxStatements">100</property>
<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
<property name="maxStatementsPerConnection"></property>
<!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能
通过多线程实现多个操作同时被执行。Default: 3-->
<property name="numHelperThreads">3</property>
<!--当用户调用getConnection()时使root用户成为去获取连接的用户。主要用于连接池连接非c3p0
的数据源时。Default: null-->
<property name="overrideDefaultUser">root</property>
<!--与overrideDefaultUser参数对应使用的一个参数。Default: null-->
<property name="overrideDefaultPassword">password</property>
<!--密码。Default: null-->
<property name="password"></property>
<!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:
测试的表必须在初始数据源的时候就存在。Default: null-->
<property name="preferredTestQuery">select id from test where id=1</property>
<!--用户修改系统配置参数执行前最多等待300秒。Default: 300 -->
<property name="propertyCycle">300</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">false</property>
<!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->
<property name="testConnectionOnCheckin">true</property>
<!--用户名。Default: null-->
<property name="user">root</property>
在Hibernate(spring管理)中的配置:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass"><value>oracle.jdbc.driver.OracleDriver</value></property>
<property name="jdbcUrl"><value>jdbc:oracle:thin:@localhost:1521:Test</value></property>
<property name="user"><value>Kay</value></property>
<property name="password"><value>root</value></property>
<!--连接池中保留的最小连接数。-->
<property name="minPoolSize" value="10" />
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize" value="100" />
<!--最大空闲时间,1800秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime" value="1800" />
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement" value="3" />
<property name="maxStatements" value="1000" />
<property name="initialPoolSize" value="10" />
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod" value="60" />
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts" value="30" />
<property name="breakAfterAcquireFailure" value="true" />
<property name="testConnectionOnCheckout" value="false" />
</bean>
编辑本段相关信息连接池配置(以Hibernate为例)
###########################
### C3P0 Connection Pool###
###########################
#hibernate.c3p0.max_size 2
#hibernate.c3p0.min_size 2
#hibernate.c3p0.timeout 5000
#hibernate.c3p0.max_statements 100
#hibernate.c3p0.idle_test_period 3000
#hibernate.c3p0.acquire_increment 2
#hibernate.c3p0.validate false
在hibernate.cfg.xml文件里面加入如下的配置:
<!-- 最大连接数 -->
<property name="hibernate.c3p0.max_size">20</property>
<!-- 最小连接数 -->
<property name="hibernate.c3p0.min_size">5</property>
<!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->
<property name="hibernate.c3p0.timeout">120</property>
<!-- 最大的PreparedStatement的数量 -->
<property name="hibernate.c3p0.max_statements">100</property>
<!-- 每隔120秒检查连接池里的空闲连接 ,单位是秒-->
<property name="hibernate.c3p0.idle_test_period">120</property>
<!-- 当连接池里面的连接用完的时候,C3P0一下获取的新的连接数 -->
<property name="hibernate.c3p0.acquire_increment">2</property>
<!-- 每次都验证连接是否可用 -->
<property name="hibernate.c3p0.validate">true</property>
其他配置

抽取工具类:

1.4.1.8、编写测试代码

public class HibernateDemo1 {
    
    //保存客户案例
    @Test
    public void demo01(){
        //1.加载Hibernate的核心配置文件
        Configuration configure = new Configuration().configure();
        //2.创建一个SessionFactory对象
        SessionFactory sessionFactory = configure.buildSessionFactory();
        //3.通过SessionFactory获取到一个session
        Session session = sessionFactory.openSession();
        //4.手动开启事务
        Transaction transaction = session.beginTransaction();

        //5.编写代码
        Customer customer = new Customer();
        customer.setCust_name("payn");
        session.save(customer);
        
        //6.事务提交
        transaction.commit();
        //7.资源释放
        session.clear();
    }
    
}
测试代码  

1.5、Hibernate的常见配置
1.5.1、XML提示配置

1.5.1.1、配置XML提示问题。eclipse下



1.5.2、Hibernate映射配置文件
1.5.2.1、映射配置文件

class 
  标签用来建立类与表的映射关系
属性:
  name :类的全路径
  table :表名(类名与表名一致,table可以省略)
  catalog :数据库名

id 
  标签用来建立类中的属性与表中的主键的对应关系
属性:
  name :类中的属性名
  column :表中的字段名(类中的属性名和表中的字段名如果一致,column可以省略)
  length :长度
  type :类型

property 
  标签用来建立类中的普通属性与表的字段的对应关系
属性:
  name :类中的属性名
  column :表中的字段名
  length :长度
  type :类型
  not-null :设置非空
  unique :设置唯一

1.5.3、Hibernate核心配置文件
1.5.3.1、核心配置文件-->配置方式
方式一:属性文件的方式    hibernate.properties
  hibernate.connection.driver_class=com.mysql.jdbc.Driver
  …
  hibernate.show_sql=true
  属性文件的方式不能引入映射文件(且需手动编写代码加载映射文件)
方式二:XML文件的方式    hibernate.cfg.xml

1.5.3.2、核心配置文件

必须的配置:
  连接数据库的基本的参数
    驱动类
    url路径
    用户名
    密码
    方言
可选的配置:
  显示SQL :hibernate.show_sql
  格式化SQL :hibernate.format_sql
  自动建表 :hibernate.hbm2ddl.auto
    none :不使用hibernate的自动建表
    create :如果数据库中已经有表,删除原有表,重新创建,如果没有表,新建表。(测试)
    create-drop :如果数据库中已经有表,删除原有表,执行操作,删除这个表。如果没有表,新建一个,使用完了删除该表。(测试)
    update :如果数据库中有表,使用原有表,如果没有表,创建新表(更新表结构)
    validate :如果没有表,不会创建表。只会使用数据库中原有的表。(校验映射和表结构)。
映射文件的引入 :
  引入映射文件的位置
    <mapping resource="com/itheima/hibernate/demo01/Customer.hbm.xml"/>

1.6、Hibernate核心API
1.6.1、Hibernate核心API
1.6.1.1、Configuration:配置对象

作用:
加载核心配置文件  
hibernate.properties
  Configuration cfg = new Configuration();
hibernate.cfg.xml
  Configuration cfg = new Configuration().configure();
加载映射文件
  // 手动加载映射
  configuration.addResource("com/itheima/hibernate/demo1/Customer.hbm.xml");

1.6.1.2、SessionFactory:Session工厂

SessionFactory内部维护了Hibernate的连接池和Hibernate的二级缓存(不讲)。是线程安全的对象。一个项目创建一个对象即可。
配置连接池:(了解)

<!-- 配置C3P0连接池 -->
<property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!--在连接池中可用的数据库连接的最少数目 -->
<property name="c3p0.min_size">5</property>
<!--在连接池中所有数据库连接的最大数目 -->
<property name="c3p0.max_size">20</property>
<!--设定数据库连接的过期时间,以秒为单位,
如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
<property name="c3p0.timeout">120</property>
<!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
<property name="c3p0.idle_test_period">3000</property>
配置c3p0连接池

抽取工具类:

/**
 * Hibernate的工具类
 */
public class HibernateUtils {
    private static Configuration configuration;
    private static SessionFactory sessionFactory;
    static {
        configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
    }
    
    public static Session openSession(){
        return sessionFactory.openSession();
    }
}
HibernateUtils.java


1.6.1.3、Session:连接对象

Session代表的是Hibernate与数据库的链接对象。不是线程安全的。与数据库交互桥梁。
Session中的API
保存方法:
  Serializable save(Object obj);
查询方法:
  T get(Class c,Serializable id);
  T load(Class c,Serializable id);
get方法和load方法的区别?
  get方法
    采用的是立即加载,执行到这行代码的时候,就会马上发送SQL语句去查询。
    查询后返回是真实对象本身。
    查询一个找不到的对象的时候,返回null
  load方法
    采用的是延迟加载(lazy懒加载),执行到这行代码的时候,不会发送SQL语句,当真正使用这个对象的时候才会发送SQL语句。
    查询后返回的是代理对象。javassist-3.18.1-GA.jar 利用javassist技术产生的代理。
    查询一个找不到的对象的时候,返回ObjectNotFoundException
修改方法:
  void update(Object obj);
删除方法:
  void delete(Object obj);
保存或更新:
  void saveOrUpdate(Object obj)

public class HibernateDemo2 {
    
    //保存客户   使用工具类 
    @Test
    public void demo01(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Customer customer = new Customer();
        customer.setCust_name("jack");
        Serializable res = session.save(customer);
        System.out.println(res);
        tx.commit();
        session.clear();
    }
    
    @Test
    public void demo02(){
        Session session = HibernateUtils.openSession();
        //开启事务
        Transaction tx = session.beginTransaction();
        
        /*
        get方法
    采用的是立即加载,执行到这行代码的时候,就会马上发送SQL语句去查询。
    查询后返回是真实对象本身。
    查询一个找不到的对象的时候,返回null
          load方法
    采用的是延迟加载(lazy懒加载),执行到这行代码的时候,不会发送SQL语句,当真正使用这个对象的时候才会发送SQL语句。
    查询后返回的是代理对象。javassist-3.18.1-GA.jar 利用javassist技术产生的代理。
    查询一个找不到的对象的时候,返回ObjectNotFoundException
        * */
        
        //使用get方法查询
//        Customer customer = session.get(Customer.class, 1L);
//        System.out.println(customer);
        //使用load方法进行查询
        Customer customer = session.load(Customer.class, 1L);
//        System.out.println(customer);
        
        tx.commit();
        session.close();
    }

    @Test
    // 修改操作
    public void demo3(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        // 直接创建对象,进行修改
        /*Customer customer = new Customer();
        customer.setCust_id(1l);
        customer.setCust_name("mills");
        session.update(customer);*/

        // 先查询,再修改(推荐)
        Customer customer = session.get(Customer.class, 1l);
        customer.setCust_name("white");
        session.update(customer);

        tx.commit();
        session.close();
    }

    @Test
    // 删除操作
    public void demo4(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        // 直接创建对象,删除
    /*    Customer customer = new Customer();
        customer.setCust_id(1l);
        session.delete(customer);*/

        // 先查询再删除(推荐)--级联删除
        Customer customer = session.get(Customer.class, 2l);
        session.delete(customer);

        tx.commit();
        session.close();
    }

    @Test
    // 保存或更新
    public void demo5(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        
        /*Customer customer  = new Customer();
        customer.setCust_name("tom");
        session.saveOrUpdate(customer);*/

        Customer customer = new Customer();
        customer.setCust_id(3l);
        customer.setCust_name("mary");
        session.saveOrUpdate(customer);

        tx.commit();
        session.close();
    }

    @Test
    // 查询所有
    public void demo6(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // 接收HQL:Hibernate Query Language 面向对象的查询语言
        Query query = session.createQuery("from Customer");
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.println(customer);
        }

        // 接收SQL:
        /*SQLQuery query = session.createSQLQuery("select * from cst_customer");
        List<Object[]> list = query.list();
        for (Object[] objects : list) {
            System.out.println(Arrays.toString(objects));
        }*/
        tx.commit();
        session.close();
    }
    
}
HibernateDemo02.java测试类

查询所有:
  Query query = session.createQuery("from Customer");
  List<Customer> list = query.list();

  SQLQuery query = session.createSQLQuery("select * from cst_customer");
  List<Object[]> list = query.list();
1.6.1.4、Transaction:事务对象
Hibernate中管理事务的对象。
  commit();
  rollback();

posted @ 2019-01-11 12:07  payn  阅读(164)  评论(0)    收藏  举报