web学习笔记25-Hibernate基本配置使用

1、看看JDBC(Java Database Connector)的一些缺点:

缺点
    1.编程的时候很繁琐,用的try和catch比较多(需要关闭ResultSet rs ,Statement stmt,Connection conn)。
    2.jdbc没有做数据的缓存(如果我们要实现每10s查询1000万条数据,没有缓存会挂掉)。
    3.没有做到面向对象编程(我们操作数据库,每次都要先拿到connect,在创建sql发送对象,执行sql,关闭对象,没有面向对象).
    4.sql语句的跨平台性很差(如果我们用mysql,后面需要切换到oracle,因为sql语句都不一样,移植很麻烦)

优点
    效率比较高(封装度越高肯定会牺牲效率的,因为hibernate底层也是用到jdbc。所以对性能要求比较高可以直接使用jdbc)。

2、看看Hibernate的一些优缺点:

hibernate的优点
    1.完全的面向对象编程(我们只要配置好xml,使用直接调用API就可以,不用写sql语句,hibernate会拼接)
    2.hibernate的缓存很厉害(一级缓存,二级缓存,查询缓存 )
    3.编程的时候就比较简单了
    4.跨平台性很强(我们替换数据库,只需要改配置文件,hibernate会拼接对应数据库的sql语句)
    5.使用场合就是企业内部的系统(因为hibernate操作数据库大于1000万条的时候会有问题,所以只适合企业内部使用,数据量不那么大)。

hibernate的缺点
    1.效率比较低
    2.表中的数据如果在千万级别,则hibernate不适合
    3.如果表与表之间的关系特别复杂,则hibernate也不适合

3、Hibernate使用步骤:

a.创建一个工程。
    就创建一个java工程就OK

b.导入jar包。

这里写图片描述
扩展知识
代理对象的三种创建方式:
1、jdkproxy(基于接口的,代理对象实现目标对象相同的接口)
2、cglib(第三方的,基于子类,代理对象是目标的子类)
3、javassist

c.hibernate.cfg.xml。

    主要的用途:
        告诉hibernate连接数据库的信息,用的什么样的数据库(方言)
        根据持久化类和映射文件生成表的策略
    /src/hibernate.cfg.xml
        <?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>
            <!-- 
                一个sessionFactory代表数据库的一个连接
            -->
            <session-factory>
                <!-- 链接数据库的用户名 -->
                <property name="connection.username">root</property>
                <!-- 链接数据库的密码 -->
                <property name="connection.password">root</property>
                <!-- 链接数据库的驱动 -->
                <property name="connection.driver_class">
                    com.mysql.jdbc.Driver
                </property>
                <!-- 链接数据库的url -->
                <property name="connection.url">
                    jdbc:mysql://localhost:3306/example_hibernate
                </property>

                <!-- 
                    方言
                    告诉hibernate使用什么样的数据库,hibernate就会在底层拼接什么样的sql语句
                    这个路径可以查看Hibernate的帮助文档,直接把路径复制过来
                -->
                <property name="dialect">
                    org.hibernate.dialect.MySQLDialect
                </property>

                <!-- 
                    根据持久化类生成表的策略(一般使用update就可以)
                    validate   通过映射文件检查持久化类与表的匹配
                    update   每次hibernate启动的时候,检查表是否存在,如果不存在,则创建,如果存在,则什么都不做了
                    create   每一次hibernate启动的时候,根据持久化类和映射文件生成表
                    create-drop
                -->
                <property name="hbm2ddl.auto">update</property>

                <!-- 
                    这个可以在控制台显示执行的sql语句,可以不写,默认不显示
                -->
                <property name="show_sql">true</property>

                <mapping
                    resource="com/example/hibernate/domain/Person.hbm.xml" />
            </session-factory>
        </hibernate-configuration>
d.编写持久化类。

    持久化类:说白了就是数据库中表的体现,字段和表中一一对应,并且有关联表的持久化类在里面。
    com.example.hibernate.domain.Person
        /**
         * 实现了Serializable的主要的作用是为了在网络上传输,实现了这个接口,jvm会把对象转化为二进制数据,便于传输。
         */
        public class Person implements Serializable{
            //字段名称和数据库的表字段对应
            private Long pid;
            private String name;
            private String description;

            public Person(){}

            public Long getPid() {
                return pid;
            }
            public void setPid(Long pid) {
                this.pid = pid;
            }
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public String getDescription() {
                return description;
            }
            public void setDescription(String description) {
                this.description = description;
            }
        }
e.编写映射文件。

    com.example.hibernate.domain.Person.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>
            <!-- 
                class用来描述一个类
                name 类的全名
                table 该持久化类对应的表名   可以不写,默认值为类名
                catalog  数据库的名称
             -->
            <class name="com.example.hibernate.domain.Person" table="person">
                <!-- 
                    用来描述主键
                    name 属性的名称
                    column 属性的名称对应的表的字段   可以不写  默认值就是属性的名称
                    length  属性的名称对应的表的字段的长度  如果不写,默认是最大的长度
                 -->
                <id name="pid" column="pid" length="5">
                    <!-- 
                        主键的产生器
                     -->
                    <generator class="increment"></generator>
                </id>

                <property name="name" length="20" type="string"></property>
                <property name="description" length="50" type="java.lang.String"></property>

            </class>
        </hibernate-mapping>
f.生成表。
        com.example.hibernate.db.CreateTable
        public class CreateTable {
            @Test
            public void testCreateTable(){
                Configuration configuration = new Configuration();
                configuration.configure();
                configuration.buildSessionFactory();
            }
        }
        这样就可以在数据中产生一个空的person表了
g.现在都配置好了,可以使用hibernate进行crud(create,retieve,update,delete)操作了。

    com.example.hibernate.crud.PersonDao
        public class PersonDao {
            /**
             * 保存person
             */
            @Test
            public void testSavePerson(){
                //加载了hibernate的配置文件
                Configuration configuration = new Configuration();
                configuration.configure();
                //configuration.configure("");//按照指定的路径加载指定的配置文件
                SessionFactory sessionFactory = configuration.buildSessionFactory();
                //产生session
                Session session = sessionFactory.openSession();
                //产生事务
                Transaction transaction = session.beginTransaction();

                //创建一个对象
                Person person = new Person("aa");
                person.setName("zhangsan");
                person.setDescription("man");

                //保存该对象
                session.save(person);

                //事务提交,session关闭
                transaction.commit();
                session.close();
            }

            @Test
            public void testGetPersonById(){
                Configuration configuration = new Configuration();
                configuration.configure();
                SessionFactory sessionFactory = configuration.buildSessionFactory();
                Session session = sessionFactory.openSession();
                /**
                 * 第一个参数为持久化类的class形式
                 * 第二个参数为主键的值
                 */
                Person person = (Person)session.get(Person.class, 1L);
                System.out.println(person.getName());
                session.close();
            }

            @Test
            public void testUpdate(){
                /**
                 * 1、先根据ID把要修改的对象查询出来
                 * 2、对对象进行修改
                 */
                Configuration configuration = new Configuration();
                configuration.configure();
                SessionFactory sessionFactory = configuration.buildSessionFactory();
                Session session = sessionFactory.openSession();
                Transaction transaction = session.beginTransaction();
                /**
                 * 先根据主键把其中的一行数据查询出来,查询出来的就是一个对象
                 */
                Person person = (Person)session.get(Person.class, 1L);
                /**
                 * 修改person对象
                 */
                person.setDescription("super man");
                //执行修改操作
                session.update(person);
                transaction.commit();
                session.close();
            }

            @Test
            public void testDelete(){
                /**
                 * 1、根据id把对象查询出来
                 * 2、删除该对象
                 */
                Configuration configuration = new Configuration();
                configuration.configure();
                SessionFactory sessionFactory = configuration.buildSessionFactory();
                Session session = sessionFactory.openSession();
                Transaction transaction = session.beginTransaction();

                /**
                 * 把pid为1的对象提取出来
                 */
                Person person = (Person)session.get(Person.class, 1L);

                //删除一个对象
                session.delete(person);

                transaction.commit();
                session.close();
            }
        }
注意:
    1.配置文件可以随意放,查看源码可以看到configure也是调用了带参的 configuration.configure("");

4、sessionFactory对象介绍:

SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。
读取hibernate.cfg.xml的时候就初始化好了。

特点:
    1.hibernate中的配置文件、映射文件、持久化类的信息都在sessionFactory中
    2.sessionFactory中存放的信息都是共享的信息
    3.sessionFactory本身就是线程安全的(如果在tomcat中,在启动的时候就已经加载好了,所以是线程安全的)
    4.一个hibernate框架sessionFactory只有一个
    5.sessionFactory是一个重量级别的类

5、session对象介绍:

提起来Session的话,首先想到的是http的session,在hibernate中的session并不是http中所说的session。
一般把HttpSession对象称为用户会话,而hibernate中的Session是用来表示,应用程序和数据库的一次交互(会话)。
通常将每个Session实例和一个数据库事务绑定,也就是每执行一个数据库事务,都应该先创建一个新的Session实例,
在使用Session后,还需要关闭Session。

特点:
    1、得到了一个session,相当于打开了一次数据库的连接
    2、在hibernate中,对数据的crud操作都是由session来完成的

6、transaction对象介绍:

hibernate中的事务默认不是自动提交的。
只有产生了连接,才能进行事务的操作。所以只有有了session以后,才能有transaction
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();//看底层源码,设置了JDBC的connection的setAutoCommit为false
    .
    .
    .
    transaction.commit();
    session.close();

7、hibernate插入数据内部的执行原理:
这里写图片描述

8、hibernate配置文件中的类型:

a.hibernate类型
    这个效率比较低,因为内部还需要转化。

b.java类型
    该种类型的效率比较高
    在hibernate内部,为了一张表,这张表中有如下的映射关系:
    hibernate类型       java类型        数据库的字段的类型
    string             java.lang.String    varchar

例如:Person.hbm.xml
    <hibernate-mapping>
        <class name="com.itheima12.hibernate.domain.Person" table="person">
            <id name="pid" column="pid" length="5">
                <generator class="increment"></generator>
            </id>
            <!-- 这个string就是Hibernate的类型 -->
            <property name="name" length="20" type="string"></property>

            <!-- 这个java.lang.String就是Java类型 -->
            <property name="description" length="50" type="java.lang.String"></property>
        </class>
    </hibernate-mapping>
一般我们用java类型就好了。

9、hibernate中主键产生机制

在配置文件 Person.hbm.xml 中配置主键的类型,我们默认使用increment。
下面介绍几种不同的类型之间的区别

 先创建一个Utils的工具类
 com.itheima12.hibernate.utils.HibernateUtils
     public class HibernateUtils {
        public static SessionFactory sessionFactory;
        static{
            Configuration configuration = new Configuration();
            configuration.configure();
            sessionFactory = configuration.buildSessionFactory();
        }
    }
a.increment
    <generator class="increment"></generator>
        /**
         * select max(pid) from person
         *    先找到主键的最大值,在最大值基础上加1
         *    所以该主键必须是数字类型,对应的持久化类里面的字段需要是数字类型
         */
        @Test
        public void testIncrement(){
            Session session = HibernateUtils.sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();

            Person person = new Person();
            person.setName("123");
            session.save(person);

            transaction.commit();
            session.close();
        }
b.assigned
    <generator class="assigned"></generator>
        /**
         * 在程序中手动的设置主键的值
         */
        @Test
        public void testAssigned(){
            Session session = HibernateUtils.sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();

            Person person = new Person();
            person.setName("123");
            person.setPid(2L);//如果不手动分配主键值,就会报错
            session.save(person);

            transaction.commit();
            session.close();
        }
c.identity
    <generator class="identity"></generator>
        /**
         * 表的自动增长机制
         *   主键必须是数字类型
         *   该效率比increment要高,但是id值不连续
         */
        @Test
        public void testIdentity(){
            Session session = HibernateUtils.sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();

            Person person = new Person();
            person.setName("123");
            session.save(person);

            transaction.commit();
            session.close();
        }
d.uuid
    <generator class="uuid"></generator>
        /**
         * uuid的字符串是由hibernate内部生成的
         *    要求主键必须是字符串类型
         */
        @Test
        public void testUUID(){
            Session session = HibernateUtils.sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();

            Person person = new Person();
            person.setName("aaa");

            session.save(person);

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

10、hibernate对象的状态(3种状态)

a.临时状态:new出来的对象在内存中
b.持久化状态:将对象加载进hibernate框架中
c.脱管状态:session使用完了,对象重新回到内存,可被GC回收。

各状态的简单示意图

这里写图片描述
现在看看session的各种方法,对象的状态是怎么转化的
持久化类,配置文件,Utils的代码同上。

a.save
        //该方法可以把一个对象从临时状态转换成持久化状态
        @Test
        public void testSave(){
            SessionFactory sessionFactory = HibernateUtils.sessionFactory;
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Person person = new Person();
            person.setName("123");
            session.save(person);
            transaction.commit();
            session.close();
        }
    b.get
        //从数据库中根据主键提取出一个对象,该对象就是一个持久化状态的对象
        @Test
        public void testGet(){
            SessionFactory sessionFactory = HibernateUtils.sessionFactory;
            Session session = sessionFactory.openSession();
            Person person = (Person)session.get(Person.class, 1L);//持久化状态
            session.close();
        }
c.update
        //把一个对象变成持久化状态
        @Test
        public void testUpdate(){
            SessionFactory sessionFactory = HibernateUtils.sessionFactory;
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();

            Person person = (Person)session.get(Person.class, 1L);//持久化状态
            person.setDescription("111");
            //session.update(person);//update方法就是把一个对象的状态变成持久化状态,person对象已经是持久化状态了,所以这行代码不需要写
            transaction.commit();
            session.close();
        }
d.evict
        //把一个对象从持久化状态转化为脱管状态
        @Test
        public void testEvict(){
            SessionFactory sessionFactory = HibernateUtils.sessionFactory;
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Person person = (Person)session.get(Person.class, 1L);//持久化状态
            person.setDescription("111");
            session.evict(person);//该方法可以把一个持久化状态变成脱管状态
            session.update(person);//由脱管状态的对象变成持久化状态
            transaction.commit();
            session.close();
        }
 e.clear
        //把所有的hibernate中的持久化对象都转换成脱管状态的对象
        @Test
        public void testClear(){
            SessionFactory sessionFactory = HibernateUtils.sessionFactory;
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();

            Person person = (Person)session.get(Person.class, 1L);//持久化状态
            person.setDescription("111");

            Person person2 = new Person();
            person2.setName("88");
            session.save(person2);//person2是一个持久化状态的对象

            session.clear();//把hibernate里面的所有的对象都变成脱管状态的对象

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

11、hibernate中的对象副本。

hibernate中只要是查询,就会创建对象的副本。副本中的数据和数据库里面的数据保持一致。

Person person = (Person)session.get(Person.class, 1L);//持久化状态

为什么要创建副本呢?
    我们不希望频繁的和数据库交互,这样效率很低。比如我们查询了一个数据,我们没有修改或者修改的值和副本中的一样,
    我们就没必要把数据再重新插入到数据库了,这样就减少了和数据库的交互,虽然会牺牲点内存。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值