hibernate 底层知识拓展

实体类规范(javaBean规范)
1.提供无参构造方法
2.成员变量私有化提供get/set方法
double 表示学分 0-100.0 没考试 0
Double 有null值 缺考 用空值表示03.基本数据类型尽量使用包装类型(可以多表示一个值null例如考试分数 缺考和0分)
4.实体中必须要提供一个与表中的主键相对应的属性id
hibernate是通过主键来区别对象是否相同
5.不要使用final修饰实体类(代理对象是要继承该类的)
主键的类型
1.自然主键
输入人的时候 人的身份证号 保证了 非空不重复  复合主键的贴点

但是身份证号 本身是业务字段  可以作为主键使用 叫做自然主键

2.代理主键(常用)
当找不到主键的时候(没有业务字段符合主键的规则)
搞一个没有任何意义的主键id列 作为主键 就是为了非空不重复 叫做代理主键
主键生成策略(7种)
identity:主键自增 有数据库来维护主键 录入的时候不需要指定主键

increment:主键自增 由hibernate来维护主键 每次插入前会先查询表中 id
最大值 +1 作为新主键
效率不高每次都要查询 如何10个人同时要保存 可能会出现线程问题

sequence:Oracle中的主键生策略 序列
hilo:高低位算法(数据库中的主键自增算法原理)由hiernate来维护主键hibernate自己算一下(无意义)

native:hilo +sequence + identity 自动三选一 检测你是什么数据库

mysql就identity Oracle就sequence 如果没有就 用hilo 但是世界上没有一个 不支持自增和序列的数据库 其实就是21 

uuid:产生一个随机的字符串作为主键 主键类型必须为string类型 

assigned:自然主键生成策略(没策略)hibernate不会管理 由开发人自己录入

三种状态

1.瞬时态 没有id 没有和session关联(这里的关联是指和缓存关联)
2.持久态 有id 有关联(这里的关联是指和缓存关联)
3.游离态 有id 没有关联(这里的关联是指和缓存关联)

测试:save get 多次 打印的语句
结论:就是将我们想要同步数据库的数据 所对应的对象转换成持久态
/* hibernate中对象的三种状态
     * 
     */
    @Test
    public void  fun(){
        //获取session
        Session session = HibernateUtils.getSession();
        //开启事物
        Transaction transaction = session.beginTransaction();
        //包裹语句
        //*******************************
        User user = new User();   //瞬时态 没有id  没有和session关联
        user.setUsername("wl");
        user.setPassword("123456");

        session.save(user); //持久态  有id 有和session关联
        // update delete  get  这三个方法是从 什么态  转  成什么态
        //*********************************
        //提交事务
        transaction.commit();
        //关闭资源
        session.close(); //游离态  有id  没有和session关联

        }

这里写图片描述

一级缓存与快照(系统实现的 将以下的实现的原理)
1一级缓存测试 get多次 打印的语句

@Test
    public void  fun2(){
        //获取session
        Session session = HibernateUtils.getSession();
        //开启事物
        Transaction transaction = session.beginTransaction();
        //包裹语句
        //*******************************
        //测试一下hibernate 中的缓存
        User user1 = session.get(User.class, 1);
        User user2 = session.get(User.class, 1);
        User user3=      session.get(User.class, 1);
        User user4 = session.get(User.class, 1);
        User user5 = session.get(User.class, 1);
        //1.生成几条sql语句
        //2.下面打印的结果
        //思考:为什么?
        //hibernate 的缓存机制
        //第一次   再一次

        System.out.println(user2==user5);

        //*********************************
        //提交事务
        transaction.commit();
        //关闭资源
        session.close(); //游离态  有id  没有和session关联

        }

这里写图片描述
2.快照 测试 get后 修改两次名字 打印的语句

@Test
    //快照测试
    public void  fun4(){
        //获取session
        Session session = HibernateUtils.getSession();
        //开启事物
        Transaction transaction = session.beginTransaction();
        //包裹语句
        //*********************************
        User user = session.get(User.class, 1);
        user.setUsername("pp");
        user.setUsername("dpp");
        session.update(user);
        //*********************************
        //提交事务
        transaction.commit();
        //关闭资源
        session.close(); //游离态  有id  没有和session关联

        }

这里写图片描述
3.测试
瞬时态 -> 游离态->持久态
new对象 -> 设置id -> update -> get

事物
        Transaction transaction = session.beginTransaction();
        //包裹语句
        //*********************************
        User user = new User();//瞬时态 没有id  和session中的缓存 没有关联
        user.setId(1);        // 游离态 有id   和session中的缓存 没有关联

        //从数据库返回结果集 是保存进缓存和快照中
        //update 时 把这个要更新的对象 放入缓存中(跟快照没关系)
        session.update(user); //持久态 有id  和session中的缓存 有关联

        //get查询时  去缓存中 查找  看有没有该id的对象
        User u = session.get(User.class, 1);
        //问:打印几条语句  为什么


        //*********************************
        //当事物提交的时候  
        //hibernate 会 对比 快照 和缓存中的对象是否相同
        //不相同 会把缓存中的对象 同步到数据库

        //提交事务
        transaction.commit();
        //关闭资源
        session.close(); //游离态  有id  没有和session关联

        }

指定事物的隔离级别

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate配置根标签 -->
<hibernate-configuration>
    <!-- session-factory 相当于数据库连接池 -->
    <session-factory>
        <!-- 加载了数据库的驱动类 基础设置 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">123456</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/a_hibernate_01</property>
        <!-- hibernate方言 配置使用哪个类 全限定类名 org.hibernate.dialect.MySQLDialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 在控制台输出sql语句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 美化sql语句 -->
        <property name="hibernate.format_sql">true</property>
        <!-- hbm2ddl.auto 是否自动生成表结构 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
                <!-- 
                    通过hibernate 来设置事物的隔离级别 
                    ## specify a JDBC isolation level       
                    #hibernate.connection.isolation 1|2|4|8
                    隔离级别是用一个字节存储的 
                    0001            1
                    0010            2   
                    0100            4
                    1000            8 -->
                    <property name="hibernate.connection.isolation">4</property>
                    <!-- 使用getCurrentSession 必须配置一下 -->
                    <!-- 注意当你使用 getCurrentSession时 不需要你手动关闭session 系统会帮你关闭 -->
                    <property name="hibernate.current_session_context_class">thread</property>
                    1.脏读
                    2.可重复读
                    3.幻读
                    READ UNCOMMITTED    读未提交   1  2  3
                    READ COMMITTED      读已提交      2  3 
                    REPEATABLE READ     可重复读      3     
                    SERIALIZABLE            串行化(只能一个一个的访问:效率非常的低) 
                     -->


        <!-- 注意:映射实体类 全文件名 从包名开始 -->
        <!-- 让配置文件知道有你这个实体类 -->
        <mapping resource="com/lanou3g/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

设置可以获取当前session 与当前线程绑定的

1.thread

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate配置根标签 -->
<hibernate-configuration>
    <!-- session-factory 相当于数据库连接池 -->
    <session-factory>
        <!-- 加载了数据库的驱动类 基础设置 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">123456</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/a_hibernate_01</property>
        <!-- hibernate方言 配置使用哪个类 全限定类名 org.hibernate.dialect.MySQLDialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 在控制台输出sql语句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 美化sql语句 -->
        <property name="hibernate.format_sql">true</property>
        <!-- hbm2ddl.auto 是否自动生成表结构 -->
        <property name="hibernate.hbm2ddl.auto">update</property>

                    <property name="hibernate.connection.isolation">4</property>
                    <!-- 使用getCurrentSession 必须配置一下 -->
                    <!-- 注意当你使用 getCurrentSession时 不需要你手动关闭session 系统会帮你关闭 -->
                    <property name="hibernate.current_session_context_class">thread</property>

        <!-- 注意:映射实体类 全文件名 从包名开始 -->
        <!-- 让配置文件知道有你这个实体类 -->
        <mapping resource="com/lanou3g/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

注意:
1.配置配置文件
2.调用getCurrentSession获取session 当事务提交 session会自动关闭 不需要手动关闭

创建实体类

public class User {
    private  int id;
    private String username;
    private  String password;

    public User() {
        super();
        // TODO Auto-generated constructor stub
    }
    public User(int id, String username, String password) {
        super();
        this.id = id;
        this.username = username;
        this.password = password;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
    }



}

简单的分装一个获取session的方法

/*
 * 简单封装
 */
public class HibernateUtils {
    // 把sessionFactory写成成员变量
    private static SessionFactory sessionFactory;
    static {
        // 加载配置文件
        Configuration configuration = new Configuration().configure();
        // 创建session工厂
        sessionFactory = configuration.buildSessionFactory();
    }
    // 返回session的方法
    public static Session getSession() {
        return sessionFactory.openSession();
    }
    // 返回当前session的方法
    public static Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }
}

获取session

public class UserDao {

    public void saveUser(User user) {
            //获取当前的session
            Session session = HibernateUtils.getCurrentSession();
            session.save(user);
    }
}

获取当前的session

public class UserService {
    private  UserDao dao = new UserDao();

        public void addUser(User user) {
                    //获取当前的session
            Session session = HibernateUtils.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            //调用dao层方法失败了怎么办?


            try {
                dao.saveUser(user);
            } catch (Exception e) {
                //可以使用异常来处理.  失败之后会报个异常.
                e.printStackTrace();
                //直接回滚事物  rollback
                transaction.rollback();
            }

            transaction.commit();
        }
}

猜你喜欢

转载自blog.csdn.net/qq_36390044/article/details/79872134