Hibernate配置文件和常用方法函数详解(二)

2022-06-18  本文已影响0人  程序猿峰岑
配置映射文件和数据库的关系
<property name="hibernate.hbm2ddl.auto">update</property>
数据库方言
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

*hbm.xml映射文件解说

实体类entity(model)的编写规则
编写规则如下
持久化对象的唯一标识OID
区分自然主键和代理主键
基本数据类型和包装类型
SQL、Hibernate和对象类型对应表
image.png
主键的生成策略【非常重要】

1、id主键,如果属性与表字段不一样需要指定column
2、column属性对应表的列名
3、type数据类型
主键生成策略 常用2、5、6、7
1、increment由hibernate自己维护自动增加,原理使用max函数,然后+1,不建议使用,因为有线程安全问题
2、identity:hibernate使用数据库自带的自动增长方式
例如:mysql是auto_increment
3、squence:hibernate使用采用数据库系统
例如:oracle提供的系统
4、hilo:hibernate自己实现的算法,自己生成主键(hilo算法)几乎不用
5、native根据数据库自动选择identity、squnce、hilo
6、uuid采用字符串唯一值
7、assigned自然主键,由程序自动维护

具体代码如下:
<!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.gfy.hibernate.domain.User" table="t_user">
        <!--1、id主键,如果属性与表字段不一样需要指定column
          2、column属性对应表的列名
          3、type数据类型-->
        <id name="uid" column="id">
            <!--主键生成策略 常用2、5、6、7
            1、increment由hibernate自己维护自动增加,原理使用max函数,然后+1,不建议使用,因为有线程安全问题
            2、identity:hibernate使用数据库自带的自动增长方式
            例如:mysql是auto_increment
            3、squence:hibernate使用采用数据库系统
            例如:oracle提供的系统
            4、hilo:hibernate自己实现的算法,自己生成主键(hilo算法)几乎不用
            5、native根据数据库自动选择identitysqunce、hilo中的几乎不用
            6、uuid采用字符串唯一值
            7、assigned自然主键,由程序自动维护-->
            <generator class="native"></generator>
        </id>
        <property name="username"></property>
        <property name="password"></property>
        <property name="gender"></property>
    </class>
</hibernate-mapping>
普通属性

class标签的dynamic-insert=“true”,是否动态生成插入语句【如果属性字段为空,就不会有这些字段的插入语句】

<class name="com.gfy.hibernate.domain.User" table="t_user" dynamic-insert="true">

class标签的dynamic-update=“true”与insert类似

type的使用和设置,如图:
image.png
Date类型

Hibernate实体的状态

状态介绍
一级缓存概念

一级缓存又称为session级别的缓存,当获得一次会话(session)、hibernate在session中创建多个集合(map)用于存放操作数据(PO对象)为程序,优化服务,如果之后需要相应的数据,hibernate优先从session中缓存中获取,如果有就使用,如果没有在查询数据库,当session关闭时,一级缓存销毁

User user = (User) session.get(User.class,1);
        System.out.println(user);
        User user1 = (User) session.get(User.class,1);
        System.out.println(user1);
移除缓存
   //方法一
    session.clear();
    //方法二
    session.evict(user)
一级缓存快照【掌握】

快照与一级缓存一样的存放位置,对一级缓存数据进行备份,保证数据库的数据与一级缓存的数据必须一致,如果一级缓存修改了,在执行commit提交时,将自己刷新为一级缓存,执行update语句,将一级缓存的数据与更新到数据库


image.png
Session session = HibernateUtils.openSession();
        session.beginTransaction().begin();
        User user = (User) session.get(User.class,1);
        user.setUsername("lisi02");
        session.beginTransaction().commit();
        session.close();
session.flush()手动刷新、保持一致缓存与数据库一致

此时会执行两条update语句,如果去除flush代码只有一条update语句

一级缓存细节

HQL的结果或会进入一级缓存,控制台查看只有一次查询语句
        List list = session.createQuery("from User").list();
        User user = (User) session.get(User.class,1);
        System.out.println(user);
SQL不会对数据进行session缓存,控制台查看有两条查询语句
        SQLQuery query = session.createSQLQuery("select * from t_user");
        System.out.println(query.list());
        User user = (User) session.get(User.class,1);
        System.out.println(user);
Criteria 对数据进行一级缓存,控制台查看只有一次查询语句
        Criteria criteria = session.createCriteria(User.class);
        System.out.println(criteria.list());
        User user = (User) session.get(User.class,1);
        System.out.println(user);
其他API

save和persist方法的区别
save方法:瞬状态转换持久态,会初始化OID
1、执行save方法,立即触发insert语句,从数据库获得的主键的值OID
2、执行save之前,设置OID将忽略
3、如果执行查询session缓存移除时,在执行save方法,将执行insert

    User user = new User();
    user.setUid(2);
    user.setUsername("April");
    user.setPassword("123456");
    user.setGender("female");
    session.save(user);
image.png
image.png

在执行save方法,立即触发insert语句,从数据库中获取主键的值

persist方法:瞬时状态转换持久态
Hibernate的多表关联关系映射
image.png

一对多:一表(主表)必须有主键,多表(从表)必须外键,主表主键与从表外键,形成主外键关系
一对一:主外键关系

案例:顾客与订单的关系

分析:一个顾客有多个订单,一个订单只能有一个顾客,因此这种关系是一对多的关系,顾客是主表
顾客类

public class Customer {
    private Integer id;
    private String name;
    private Set<Order> orders = new HashSet<Order>();

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Order> getOrders() {
        return orders;
    }

    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }
}

订单类

public class Order {
    private Integer id;
    private String orderNo;
    private Customer customer;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
}

Customer.hbm.xml

<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.gfy.hibernate.domain">
    <class name="Customer" table="t_customer">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"></property>
        <set name="orders">
            <key column="customer_id"></key>
            <one-to-many class="Order"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

Order.hbm.xml

<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.gfy.hibernate.domain">
    <class name="Order" table="t_order">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="orderNo"></property>
        <many-to-one name="customer" column="customer_id"></many-to-one>
    </class>
</hibernate-mapping>

具体执行的代码如下:

        Session session = HibernateUtils.openSession();
        session.beginTransaction().begin();
        Customer customer = new Customer();
        customer.setName("April");
        Order order = new Order();
        order.setCustomer(customer);
        order.setOrderNo("JD"+Math.random()*10000);
        order.setName("lipstick");

        Order order1 = new Order();
        order1.setCustomer(customer);
        order1.setOrderNo("TB"+Math.random()*10000);
        order1.setName("eyebrow pencil");

        Set<Order> orders = new HashSet<>();
        orders.add(order);
        orders.add(order1);
        customer.setOrders(orders);
        //因为订单依赖主键的id 所以这里需要先保存顾客
        session.save(customer);
        session.save(order);
        session.save(order1);
        session.beginTransaction().commit();
        session.close();
数据库查询结果
image.png
image.png

那么问题来了,为啥我们在执行上面的代码的时候查询数据库在没有创建顾客和订单表的情况下能够查询到这两张表的数据呢,表是如何创建和插入数据的,其实我们在文章开头都已经讲过了,配置文件配置如下就可以了

<property name="hibernate.hbm2ddl.auto">update</property>

当然我们还需要把JavaBean实体类的映射属性和数据库表的属性进行关联

<mapping resource="com/gfy/hibernate/domain/Customer.hbm.xml"/>
        <mapping resource="com/gfy/hibernate/domain/Order.hbm.xml"/>
上一篇下一篇

猜你喜欢

热点阅读