Hibernate的介绍及使用

一、什么是hibernate

  • hibernate是一个轻量级javaEE持久层框架,是一个ORM框架(对象关系映射,所以这类框架都有个对象关系映射文件xxx.hbm.xml)
    在web项目中对数据库的操作流程是–application–>hibernate–>database,hibernate在里面就是连接请求与数据库的桥梁,核心配置文件xxx.hbm.xml用于连接application,hibernate.cfg.xml用于连接database
  • ORM 表示 Object-Relational Mapping (ORM)
    O:object:对象
    R:Relational:关系
    M:mapping:映射

二、hibernate的属性

a、configuration

  • 读取hibernate.cfg.xml
  • 管理对象关系映射文件xxx.hbm.xml
  • 加载hibernate的配置信息 创建对象Configuration config=new Configuration().configure();

b、SessionFactory

  • 缓存sql语句,数据(一级缓存,session级缓存)
  • 在应用程序初始化的时候创建,重量级类,一个数据库只要有一个就可以了(为什么叫重量级的类呢,因为sessionFactory管理着连接数据库的会话,网站运行时连接时很重要的,而且存储了大量sql语句或数据,占用了大量内存)
  • SessionFactory负责创建Session实例,可以通过Configuration实例构建SessionFactory
    sessionFactory= new Configuration().configure().buildSessionFactory();

Session作用

  • Session时hibernate数据持久化的基础,可以看作持久化管理工具,提供了很多持久化方法 ,通过这些方法,完成curd操作(save/delete/get/load/update)
  • 通常一个数据库事物和一个Session事例绑定,每执行一个事物都要创建一个Session,使用后需要手动关闭
  • Session时线程不同步的(不安全),所以要保证在同一线程中使用,可以 用getCurrentSession
  • Session实例由SessionFactory构建–Session session=sessionFactory.openSession();)

c、openSession和getCurrentSession区别

  • openSession是一个全新的Session getCurrentSession时获取一个和事务绑定的Session
  • getCurrentSession在commit后自动关闭,openSession不会 getCurrentSession在hibernatecfg.xml还要配置

三、hibernate的全局配置文件

  • 配置方言
<property
name="hibernate.dialect">org.hibernate.dialect.MySQL5Diale
ct</property>

四、hibernate的简单案例编写

  • 编写一个员工实体类
package com.cn.lin;import java.util.Date;/*** @Author Lin_Home* @Date 2020/10/10 18:31* @Version 1.0*/
public class Employee {private Integer id;private String name;private String email;private Date hiredate;public Employee() {}public Employee(Integer id, String name, String email, Date hiredate) {this.id = id;this.name = name;this.email = email;this.hiredate = hiredate;}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 String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Date getHiredate() {return hiredate;}public void setHiredate(Date hiredate) {this.hiredate = hiredate;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", name='" + name + '\'' +", email='" + email + '\'' +", hiredate=" + hiredate +'}';}
}
  • 编写一个工具类
package com.cn.lin;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;/*** @Author Lin_Home* @Date 2020/10/10 18:56* @Version 1.0*/
public class HibernateUtils {//编写hibernate的工具类private static SessionFactory sessionFactory;static {//创建配置对象Configuration configuration = new Configuration().configure();//建立sessionFactory对象sessionFactory = configuration.buildSessionFactory();}public static Session openSession(){//建立会话return sessionFactory.openSession();}}
  • 编写一个测试类
package com.cn.lin;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.jupiter.api.Test;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;/*** @Author Lin_Home* @Date 2020/10/10 18:38* @Version 1.0*/
public class MainTest {/*** 实现添加数据* */public static void main(String[] args) {//创建配置对象,他会读取hibernate.cfg.xml文件Configuration configuration = new Configuration().configure();//创建一个会话 SessionFactory对象SessionFactory sessionFactory = configuration.buildSessionFactory();//连接会话Session session =sessionFactory.openSession();//开启事务Transaction transaction = session.beginTransaction();Employee employee = new Employee();employee.setEmail("1415318251@qq.com");employee.setName("Yee");long timeMillis = System.currentTimeMillis();Date date = new Date(timeMillis);SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");simpleDateFormat.format(date);employee.setHiredate(date);session.save(employee);transaction.commit();//关闭会话session.close();}//删除@Testpublic void deleteByIdTest() {Session session = HibernateUtils.openSession();// 4.开启事务Transaction transaction = session.beginTransaction();// 5.执行持久化操作Employee user = session.get(Employee.class, 1);session.delete(user);// 6.提交事务transaction.commit();// 7.关闭资源session.close();}//修改@Testpublic void UpdateTest(){Session session = HibernateUtils.openSession();//开启事务Transaction transaction = session.beginTransaction();Employee employee = new Employee();employee.setId(2);employee.setEmail("141551@qq.com");employee.setName("Woo");long timeMillis = System.currentTimeMillis();Date date = new Date(timeMillis);SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");simpleDateFormat.format(date);employee.setHiredate(date);session.update(employee);transaction.commit();//关闭会话session.close();}/*** 单查询根据id* */@Testpublic void QueryById(){Session session = HibernateUtils.openSession();Transaction transaction = session.beginTransaction();Employee user = session.get(Employee.class, 2);System.out.println(user);transaction.commit();session.close();}//全查询 from 对应的是实体类命名@Testpublic void QueryTest(){Session session = HibernateUtils.openSession();Transaction transaction = session.beginTransaction();Query query = session.createQuery("from Employee ");//2、使用Query对象的list方法得到数据集合List<Employee> list = query.list();for(Employee employee:list){System.out.println(employee.getId()+" "+ employee.getName()+" "+employee.getEmail()+" "+employee.getHiredate());}transaction.commit();session.close();}//条件查询@Testpublic void QueryByCondition(){Session session = HibernateUtils.openSession();Transaction transaction = session.beginTransaction();Query query = session.createQuery("from Employee where name = :name");query.setParameter("name","Yee");//2、使用Query对象的list方法得到数据集合List<Employee> list = query.list();for(Employee employee:list){System.out.println(employee.getId()+" "+ employee.getName()+" "+employee.getEmail()+" "+employee.getHiredate());}transaction.commit();session.close();}
}
  • 实体类的配置文件
<?xml version="1.0"?>
<!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.cn.lin"><class name="com.cn.lin.Employee" table="employee"><id name="id"><!--            数据库的主键交给数据库本地管理--><generator class="native"></generator><!--            主键实现自增长-->
<!--            <generator class="identity"></generator>--><!--            自增主键,由Hibernate维护,插入数据前,先从数据库中读取主键最大值+1作为本次主键-->
<!--            <generator class="increment"></generator>--><!--            使用的是String 类型,并且是32位的,自动生成id-->
<!--            <generator class="uuid"></generator>--><!--            Oracle数据库中主键生成策略-->
<!--            <generator class="sequence"></generator>--></id><property name="name" column="name"/><property name="email" column="email"></property><property name="hiredate" column="hiredate"></property></class></hibernate-mapping>
  • hibernate的生成文件配置
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory><property name="connection.url">jdbc:mysql://localhost:3306/hello</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property><property name="connection.username">账号</property><property name="connection.password">密码</property><!--  导入配置文件的路径  --><mapping resource="Employee.hbm.xml"></mapping></session-factory></hibernate-configuration>

五、Hibernate的主键生成策略

  • 开发中尽量使用代理主键,这样可以在主键发生变化的时候不用修改源代码,也满足OCP原则。
  • ocp原则介绍:https://blog.csdn.net/benbenxiongyuan/article/details/24021039

a、increment

  • hibernate中提供的自动增长机制,适用于short、int、long类型的主键。仅单线程程序中使用。原理:首先发送一条语句:select MAX(id) from 表;然后将id+1作为下一条记录的主键。

b、identity

  • 使用数据库底层的自动增长机制,适用于short、long、int。适用于有自动增长机制的数据库(MySQL、MSSQL)。 注意:Oracle是没有自动增长的。

c、 sequence

  • 采用序列机制,适用于short、int、long。适用于序列机制的数据库(Oracle)

d、uuid

  • uuid 适用于字符串类型主键。使用hibernate中随机方式生成字符串主键。 它会生成唯一的32位的16进制的字符串

e、native

  • 本地策略。可以在identity和sequence间进行自动切换。

f、assigned

  • hibernate放弃外键管理。需要通过手动编写程序或用户自己设置。

g、foreign

  • 外部的。会在一对一的关联映射下使用。

六、hibernate一对多关系用法

-- 客户表
CREATE TABLE t_customer(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
gender CHAR(1)
);
-- 订单表
CREATE TABLE t_order(
id INT PRIMARY KEY AUTO_INCREMENT,
orderno VARCHAR(20),
product_name VARCHAR(20),
cust_id INT,
CONSTRAINT order_customer_fk FOREIGN KEY(cust_id) REFERENCES
t_customer(id)
);
  • 编写一的实体类
package com.lin.cn;import java.util.Set;/*** @Author Lin_Home* @Date 2020/10/11 14:38* @Version 1.0*/
public class Customer {//idprivate Integer id;//用户名private String name;//性别private String gender;//客户对应的多个订单号private Set<Order> order;public Customer() {}public Customer(Integer id, String name, String gender, Set<Order> order) {this.id = id;this.name = name;this.gender = gender;this.order = 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 String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public Set<Order> getOrder() {return order;}public void setOrder(Set<Order> order) {this.order = order;}@Overridepublic String toString() {return "Customer{" +"id=" + id +", name='" + name + '\'' +", gender='" + gender + '\'' +", order=" + order +'}';}
}
  • 编写多的实体类
package com.lin.cn;/*** @Author Lin_Home* @Date 2020/10/11 14:41* @Version 1.0*/
public class Order {//订单idprivate Integer id;//订单编号private String orderno;//产品名private String productName;//体现一个订单所属一个客户(one)private Customer customer;public Order() {}public Order(Integer id, String orderno, String productName, Customer customer) {this.id = id;this.orderno = orderno;this.productName = productName;this.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 String getProductName() {return productName;}public void setProductName(String productName) {this.productName = productName;}public Customer getCustomer() {return customer;}public void setCustomer(Customer customer) {this.customer = customer;}@Overridepublic String toString() {return "Order{" +"id=" + id +", orderno='" + orderno + '\'' +", productName='" + productName + '\'' +", customer=" + customer +'}';}
}
  • 测试类
package com.lin.cn;import com.sun.org.apache.xpath.internal.operations.Or;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.jupiter.api.Test;import java.util.HashSet;
import java.util.Set;/*** @Author Lin_Home* @Date 2020/10/11 14:56* @Version 1.0*/
public class MainTest {@Testpublic void insertTest(){//建立会话Session session = HibernateUtils.openSession();//建立事务Transaction transaction = session.beginTransaction();//开始实体类的赋值Customer customer = new Customer();customer.setName("苍井空");customer.setGender("女");Order order = new Order();order.setOrderno("订单一号");order.setProductName("剧情片场");Order order2  = new Order();order2.setOrderno("订单二号");order2.setProductName("上门片场");Set<Order> orderSet = new HashSet<>();orderSet.add(order);orderSet.add(order2);order.setCustomer(customer);order2.setCustomer(customer);customer.setOrder(orderSet);//建立持久会话session.save(customer);
//        session.save(order);
//        session.save(order2);transaction.commit();}//全部查询@Testpublic void queryAllTest(){Session session = HibernateUtils.openSession();Transaction transaction = session.beginTransaction();}//查询客户@Testpublic  void queryCustomer() {Session session=HibernateUtils.openSession();Customer customer=session.get(Customer.class,1);System.out.println("客户名="+customer.getName());for (Order order : customer.getOrder()) {System.out.println("订单名 ="+order.getProductName() +"-----订单编号"+order.getOrderno());}}//查询订单@Testpublic  void queryOrder() {Session session=HibernateUtils.openSession();Order order=session.get(Order.class,1);System.out.println("订单名="+order.getProductName());System.out.println("订单所属的客户 ="+order.getCustomer().getName() +"-------订单编号"+order.getOrderno());}//数据修改@Testpublic void delete(){Session session = HibernateUtils.openSession();Transaction transaction = session.beginTransaction();Customer customer = session.get(Customer.class, 1);session.delete(customer);transaction.commit();session.close();}}
  • 配置文件

customer 的配置文件

<?xml version="1.0"?>
<!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.lin.cn"><class name="com.lin.cn.Customer" table="t_customer"><id name="id"><!--            数据库的主键交给数据库本地管理--><generator class="native"></generator></id><property name="name" column="name"/><property name="gender" column="gender"></property><!--        对应的是集合    name对应的是集合的变量名  key对应的是数据库中关联表的外键名  class值的是对表中的那个类名-->
<!--        cascade实现级联操作 这个是 实现 添加修改--><set name="order" cascade="save-update,delete"><key column="cust_id"/><one-to-many class="Order" /></set></class></hibernate-mapping>
  • order的配置文件
<?xml version="1.0"?>
<!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.lin.cn"><class name="com.lin.cn.Order" table="t_order"><id name="id"><!--            数据库的主键交给数据库本地管理--><generator class="native"></generator></id><property name="orderno" column="orderno"/><property name="productName" column="product_name"></property><!--对应的是集合    name对应的是集合的变量名的主键  column对应的是数据库中关联表的外键名 这边的class指的是映射one表 --><many-to-one name="customer" column="cust_id" class="Customer"/></class></hibernate-mapping>
  • 生成的映射文件
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory><property name="connection.url">jdbc:mysql://localhost:3306/hello</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property><property name="connection.username">root</property><property name="connection.password">123456</property><property name="hibernate.show_sql">true</property><!-- 配置显示sql语句 -->
<!--    <property name="format_sql">true</property>&lt;!&ndash; 让输出的sql语句格式化 &ndash;&gt;--><mapping resource="Customer.hbm.xml"></mapping><mapping resource="Order.hbm.xml"/></session-factory>
</hibernate-configuration>

a、级联操作

  • 只要与此添加的对象相关的对象,它会连同持久化处理(添加或者修改)
                  <set name="orderSet" cascade="save-update">
                 <key column="cust_id" />
                <one-to-many class="Order"/>
  • 删除此对象,连同此对象的相关对象也删除( 要小心配置 )删除
          <set name="orderSet" cascade="save-update,delete">
          <key column="cust_id" />
          <one-to-many class="Order"/></set>

b、inverse用法

1、作用
如果inverse为true,则放弃外键控制
如果inverse为false,则不放弃外键关系控制
2、用法
针对一方配置,多方inverse配置不起作用,不管inverse如何配置,多方它都会维护外键处理
用法
在一方配置inverse属性
输出sql语句,发现update语句不见了

          <set name="orderSet" inverse="true">
          <key column="cust_id" />
        <one-to-many class="Order"/>

七、多对多关联问题

1、什么是多对多

  • 举例以用户表与角色表为例

    • 一个用户可以所属多个角色
    • 一个角色里面可以有多个用户

2、多对多表关系实现

  • 多对多的关联表的实现要依赖于中间表

    • 中间表的user_id的字段其实就是用户表的主键
    • 中间表的role_id的字段其实就是角色表的主键

3、编写实体对象

  • 编写用户对象

    • 注意定义一个Set集合属性,存储一个用户对应多个角色
    package com.gec.domain;import java.util.Set;/*
    * 定义用户类
    * */
    public class User {private Integer id;private String name;public User() {}public User(Integer id, String name) {this.id = id;this.name = name;}//体现多角色,使用Set集合存储private Set<Role> roleSet;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<Role> getRoleSet() {return roleSet;}public void setRoleSet(Set<Role> roleSet) {this.roleSet = roleSet;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
    }
  • 编写角色对象

    • 注意一个角色可以配置多个用户,因此定义Set集合userSet属性
    package com.gec.domain;import java.util.Set;/*
    * 角色类
    * */
    public class Role {private Integer roleId;private String roleName;//一个角色可以有多个用户private Set<User> userSet;public Role() {}public Role(Integer roleId, String roleName) {this.roleId = roleId;this.roleName = roleName;}public Integer getRoleId() {return roleId;}public void setRoleId(Integer roleId) {this.roleId = roleId;}public String getRoleName() {return roleName;}public void setRoleName(String roleName) {this.roleName = roleName;}public Set<User> getUserSet() {return userSet;}public void setUserSet(Set<User> userSet) {this.userSet = userSet;}
    }

4、编写映射文件

  • 用户的映射文件(User.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.gec.domain"><class name="User" table="t_user"><id name="id" column="id"><generator class="identity" /></id><property name="name" column="name"></property><!--Set集合映射,映射(一个用户所属多个角色)table:描述多对多所依赖的中间表表名--><set name="roleSet" table="t_user_role"><!---此key的字段就是配置中间表的外键,它指向用户表的主键--><key column="fk_user_id"></key><!---此column的字段就是配置中间表的外键,它指向角色表的主键--><many-to-many class="Role" column="fk_role_id"/></set></class></hibernate-mapping>
    
  • 角色的映射文件(Role.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.gec.domain"><class name="Role" table="t_role"><id name="roleId" column="roleId"><generator class="identity" /></id><property name="roleName" column="roleName"></property><!--Set集合映射,映射(一个用户所属多个角色)table:描述多对多所依赖的中间表表名--><set name="userSet" table="t_user_role"><!---此key的字段就是配置中间表的外键,它指向角色表的主键--><key column="fk_role_id"></key><!---此column的字段就是配置中间表的外键,它指向用户表的主键--><many-to-many class="User" column="fk_user_id"/></set></class></hibernate-mapping>
    

5、编写全局配置文件

  • 编写hibernate.cfg.xml

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration><session-factory><!--jdbc驱动类名--><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_db</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">1111</property><!--配置数据库的方言--><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!--是否显示sql语句--><property name="hibernate.show_sql">true</property><!--hibernate自构建数据库表--><property name="hibernate.hbm2ddl.auto">create</property><!--指明映射文件的路径--><mapping resource="com/gec/domain/User.hbm.xml"/><mapping resource="com/gec/domain/Role.hbm.xml"/></session-factory>
    </hibernate-configuration>
    

6、操作数据的主类

package com.gec.test;import com.gec.dbtuils.HibernateUtils;
import com.gec.domain.Role;
import com.gec.domain.User;
import org.hibernate.Session;
import org.hibernate.Transaction;import java.util.HashSet;
import java.util.Set;public class MainTest {public static void main(String[] args) {// insert();queryUser();}public static void insert(){//创建用户对象User user01=new User();user01.setName("小苍");User user02=new User();user02.setName("小罗");//创建角色对象Role role01=new Role();role01.setRoleName("超级管理员");Role role02=new Role();role02.setRoleName("普通管理员");//创建一个角色集合,将此角色添加到小苍用户Set<Role> roleSet=new HashSet<>();roleSet.add(role01);roleSet.add(role02);user01.setRoleSet(roleSet);Set<Role> roleSet2=new HashSet<>();roleSet2.add(role02);user02.setRoleSet(roleSet2);//相互关联操作//定义集合,存储用户对象Set<User> userSet=new HashSet<>();userSet.add(user01);//role01.setUserSet(userSet);Set<User> userSet2=new HashSet<>();userSet2.add(user01);userSet2.add(user02);//role02.setUserSet(userSet2);Session session= HibernateUtils.openSession();Transaction tr=session.beginTransaction();//针对对象作持久化处理session.save(user01);session.save(user02);session.save(role01);session.save(role02);tr.commit();session.close();}//实现查询public static void queryUser(){Session session=HibernateUtils.openSession();User user=session.get(User.class,1);System.out.println("此用户名="+user.getName());for (Role role : user.getRoleSet()) {System.out.println("此用户所属的角色="+role.getRoleName());}}
}

八、实现一对一关系

1、什么是一对一关系?

  • 两个元素之间它们是唯一匹配的关系

    • 举例

      • 公民都有唯一的身份证

        公民------->身份证
        身份证------>公民
        

2、如何设计一对一的数据表关系

  • 如何设计数据表

    • 方案一:

      • 唯一外键关联

        • 特点

          • 针对外键作唯一的约束

    • 方案二:

      • 主键关联

        • 特点

          • 此字段既是主键,也是外键

3、如何实现唯一的外键关联

a、对象的设计

  • 公民的实体类对象

    package com.gec.domain;public class Person {private Integer id;private String personName;//以对象方式描述用户所分配的身份证private Card card;public Person() {}public Person(Integer id, String personName) {this.id = id;this.personName = personName;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getPersonName() {return personName;}public void setPersonName(String personName) {this.personName = personName;}public Card getCard() {return card;}public void setCard(Card card) {this.card = card;}@Overridepublic String toString() {return "Person{" +"id=" + id +", personName='" + personName + '\'' +'}';}
    }
  • 身份证的实体类对象

    package com.gec.domain;public class Card {private Integer id;private String cardNo;//以对象方式描述身份证所属唯一的公民private Person person;public Card() {}public Card(Integer id, String cardNo) {this.id = id;this.cardNo = cardNo;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getCardNo() {return cardNo;}public void setCardNo(String cardNo) {this.cardNo = cardNo;}public Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}@Overridepublic String toString() {return "Card{" +"id=" + id +", cardNo='" + cardNo + '\'' +'}';}
    }

b、映射文件的配置

  • 针对Person实体类的映射配置文件

    <!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.gec.domain"><class name="Person" table="t_person"><id name="id" column="id"><generator class="identity" /></id><property name="personName" column="person_name"></property><!--针对身份证对象属性映射处理--><!--一对一的配置--><one-to-one name="card" class="Card"/></class></hibernate-mapping>
    
  • 针对身份证的实体类映射文件

    <!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.gec.domain"><class name="Card" table="t_card"><id name="id" column="id"><generator class="identity" /></id><property name="cardNo" column="cardNo"></property><!--配置多对一,但外键受唯一约束,其实就是一对一--><many-to-one name="person" column="person_id" unique="true"/></class></hibernate-mapping>
    

c、全局配置文件

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory><!--jdbc驱动类名--><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_db</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">1111</property><!--配置数据库的方言--><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!--是否显示sql语句--><property name="hibernate.show_sql">true</property><property name="hibernate.hbm2ddl.auto">update</property><mapping resource="com/gec/domain/Person.hbm.xml" /><mapping resource="com/gec/domain/Card.hbm.xml" /></session-factory>
</hibernate-configuration>

d、实现主类

package com.gec.test;import com.gec.dbutils.HibernateUtils;
import com.gec.domain.Card;
import com.gec.domain.Person;
import org.hibernate.Session;
import org.hibernate.Transaction;public class MainTest {public static void main(String[] args) {//insert();findPerson();}public static void insert(){//创建Person对象Person p=new Person();p.setPersonName("小苍");//创建身份证对象Card c=new Card();c.setCardNo("sn001");//相互关联p.setCard(c);c.setPerson(p);Session session=HibernateUtils.openSession();Transaction tr=session.beginTransaction();//针对公民及身份证作对象的持久化处理session.save(p);session.save(c);tr.commit();session.close();}public static void findPerson(){Session session=HibernateUtils.openSession();Transaction transaction=session.beginTransaction();Person p=session.get(Person.class,1);System.out.println("用户名="+p.getPersonName());System.out.println("对应的身份证="+p.getCard().getCardNo());transaction.commit();session.close();}
}

4、主键关联

a、简介

  • 表的字段既是主键,又是外键

b、对象实现

  • 对象实现如上述一致

c、映射配置文件实现

  • 主要修改card.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.gec.domain"><class name="Card" table="t_card"><id name="id" column="id"><generator class="identity" /></id><property name="cardNo" column="cardNo"></property><!--主键关联constrained属性:使用主键作为外键关联--><!--<many-to-one name="person" column="person_id" unique="true"/>--><one-to-one name="person" class="Person" constrained="true"/></class></hibernate-mapping>
    

九、查询功能

  • HQL 查询

  • QBC查询

  • 支持sql查询

    https://www.cnblogs.com/yizhichenfen/p/11319681.html对应的使用方式

十、对象状态问题

1、状态类别

  • 临时态

    • 此对象没有OID值,并且不受session对象所管理

      • OID:object的ID值,
  • 持久态
    • 此对象有 OID值,并且受session所管理
  • 游离态
    • 此对象有OID值,已经脱离了session所管理

2、举例

  • 临时态----》持久态----》游离态

    package com.gec.test;import com.gec.domain.Employee;
    import com.gec.utils.HibernateUtils;
    import org.hibernate.Session;
    import org.hibernate.Transaction;public class MainTest {public static void main(String[] args) {objectstatus();}public static void objectstatus(){//创建一个Employee对象,此对象处于临时状态Employee employee=new Employee();employee.setEmpName("周杰伦");employee.setJob("C++开发");employee.setSalary(100000.00);employee.setHiredate(new java.util.Date());Session session= HibernateUtils.openSession();Transaction transaction=session.beginTransaction();//从临时态----->持久态/**   持久态的特点:*   1、OID有值*   2、受session所管理* */session.save(employee);System.out.println("处于持久态的id值="+employee.getId());transaction.commit();session.close();//employe它就会处于游离态System.out.println("处于游离态的id值="+employee.getId());}
    }
  • 状态转换

十一、缓存详解

  • 减少访问数据库的次数,提高访问数据的效率

2、验证一级缓存是否存在

  • 举例

    //测试缓存是否启作用public static void testCache(){Session session= HibernateUtils.openSession();Transaction transaction=session.beginTransaction();//获取id=5的对象//employee此对象处于持久态Employee employee=session.get(Employee.class,5);System.out.println(employee.getEmpName());//此处是使用缓存获取对象数据Employee employee2=session.get(Employee.class,5);System.out.println(employee2.getEmpName());transaction.commit();session.close();}
    

3、如何清除一级缓存对象

  • 只需要调用以下方法即可

     session.evict(employee);
    session.clear();
    
  • 一级缓存其实它的作用域就是session对象,一级缓存hibernate是默认启动

  • 二级缓存它的作用域就是SessionFactory,二级缓存默认是不启动

4、如何配置二级缓存

a、导入encache库

  • 导入第三方缓存工具:EhCache

b、配置hibernate.cfg.xml

  • 启动二级缓存

  • 配置encache

  • 需要哪个类使用二级缓存

    <!-- 开启 Hibernate 的二级缓存 --><property name="hibernate.cache.use_second_level_cache">true</property><!-- 引入 EhCache 的工具 --><property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property><class-cache class="实体类路径" usage="read-only" />
    

c、编写主类,测试二级缓存

Session session= HibernateUtils.openSession();Transaction transaction=session.beginTransaction();//获取id=5的对象//employee此对象处于持久态Employee employee=session.get(Employee.class,5);System.out.println(employee.getEmpName());transaction.commit();session.close();Session session2=HibernateUtils.openSession();//此处是使用缓存获取对象数据Employee employee2=session2.get(Employee.class,5);System.out.println(employee2.getEmpName());session2.close();

十二、延时加载

  • get 和 load的区别

  • load :是存在延时加载(当调用到load 返回来的数据时,才显示sql语句,当是没有执行的时候是存在延时加载)[QueryById]方法

  • get:不存在延时加载,只要调用了get这个方法,直接执行hql 语句**【QueryById2】**

    @Testpublic void QueryById(){Session session = HibernateUtils.openSession();Transaction transaction = session.beginTransaction();Employee user = session.load(Employee.class, 2);
//        System.out.println(user);transaction.commit();session.close();}@Testpublic void QueryById2(){Session session = HibernateUtils.openSession();Transaction transaction = session.beginTransaction();Employee user = session.get(Employee.class, 2);
//        System.out.println(user);transaction.commit();session.close();}
  • 配置文件下 设置:lazy=“false”:放弃延时加载 true 是开启延时

1、类延时加载

<!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.gec.domain"><class name="Employee" table="t_employee" lazy="false"><id name="id" column="id"><generator class="native" /></id><property name="empName" column="emp_name"></property><property name="salary" column="salary" type="java.lang.Double"></property><property name="job" column="job" type="java.lang.String"></property><property name="hiredate" column="hiredate" type="java.util.Date"></property></class></hibernate-mapping>

2、类属性延时

  • 与表关联的延时加载问题,以一对多为例讲解

  • 可以针对一方,设置lazy=true,则支持延时加载,否则放弃延时加载

    • 配置一方的延时加载实现

       <set name="orderSet" lazy="true"><!--设置外键字段--><key column="cust_id" /><!--指明多方的类名--><one-to-many class="Order"/></set>
      
      • 配置lazy=true(默认),则支持延时加载 ,当查询客户对象,只要没有用于order属性对象,,是不会生成sql语句,查询order表内容
      • 配置layz=false,不管客户是否使用order属性,都会生成查询订单的sql语句,执行sql
    • 配置多方的延时加载实现

      <!--映射one的对象--><many-to-one name="customer" column="cust_id" class="Customer" lazy="false"/>
      
      • 配置lazy=true(默认),则支持延时加载 ,当查询订单对象,只要没有用到客户对象属性,则不会生成查询客户对象的sql语句

十三、抓包策略

  • hibernate有如下四种原生态的Hibernate抓取策略,分别是:select fetching ,join fetching,subselect fetching,Batch fetching。
  • 配置fetch属性

    • select(默认)

      生成n条sql第一条sql:select * from customer where c.id=1;第二条sql: select * from order where o.cust_id=1;
      
    • join

      • 生成多表关联查询

         它只会生成一条sql:select c.*,o.* from customer c left join order o on c.id=o.cust_id where c.id=1
        
    • subselect(针对createQuery起作用)

      • 生成子查询

        select * from order o where o.cust_id in (select c.id from customer c)
        

十四、Threadlocal管理session

1、为什么要使用ThreadLocal管理session

  • session是线程不安全的,因此在多线程环境下,session对象不能为共享对象
  • 每次运行都要打开及关闭session对象,导致性能受影响
  • 如果直接调用sessionfactory.openSession方法,获取session对象,则无法在业务层获取实现事务管理

2、如何配置session受threadlocal管理

a、写法一:

  • 自定义session受Threadlocal管理的实现

    /*
    * 定义hibernate的工具类
    * 受ThreadLocal管理session
    * */
    public class HibernateUtils {private static SessionFactory sf=null;// 使用线程局部模式//它其实就是一个map集合/**   key:就是线程id*   value:Session对象* */private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();//静态初始化块只加载一次static {//创建配置对象,它会默认读取hibernate.cfg.xml文件Configuration configuration=new Configuration().configure();//创建一个SessionFactory对象sf=configuration.buildSessionFactory();}public static Session getCurrentSession(){//先判断threadlocal是否已经存在当前线程的session,如果不存在,才创建session对象Session session = threadLocal.get();if(session==null){session=sf.openSession();threadLocal.set(session);}return session;}
    }
    

b、写法二:

  • 通过配置实现

    • 配置hibernate.cfg.xml文件

      <property name="hibernate.current_session_context_class">thread</property>
      
    • 修改Hibernate工具类代码

          public static Session openSession(){return sf.getCurrentSession();}
      

Hibernate入门及知识点使用相关推荐

  1. Hibernate入门4.核心技能

    Hibernate入门4.核心技能 20131128 代码下载 链接: http://pan.baidu.com/s/1Ccuup 密码: vqlv 前言: 前面学习了Hibernate3的基本知识, ...

  2. 杨老师课堂之JavaEE三大框架Hibernate入门第一课

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/kese7952/article/details/80998421 本篇任务 1. 使用Hiberna ...

  3. php函数知识点,php入门学习知识点七 PHP函数的基本应用_php基础

    /* * 简单的函数 */ function fontBold($con){ return "$con"; } $str="简单的函数测试!"; echo &q ...

  4. Hibernate4实战 之 第一部分 Hibernate入门

    第一部分:Hibernate入门 Hibernate是什么 Hibernate是一个轻量级的ORMapping框架 ORMapping原理(Object Relational Mapping) ORM ...

  5. Hibernate 入门之轻松上手 选择自 chainshun 的 Blog

    我找到的所有Hibernate入门文章分为三类:          1.剖析的很透彻,但是例子里面只有主要代码,不能编译执行.          2.举的例子只能在某种环境中执行,例如tomcat.  ...

  6. Hibernate入门这一篇就够了

    前言 本博文主要讲解介绍Hibernate框架,ORM的概念和Hibernate入门,相信你们看了就会使用Hibernate了! 什么是Hibernate框架? Hibernate是一种ORM框架,全 ...

  7. Hibernate入门案例及增删改查

    一.Hibernate入门案例剖析: ①创建实体类Student 并重写toString方法 public class Student {private Integer sid;private Int ...

  8. hibernate入门二之单表操作

    友情提醒:以下所有的操作都是在hibernate入门一的基础上操作的,参考链接:https://www.cnblogs.com/lindaiyu/p/10990525.html 单一主键 assign ...

  9. Arduino入门小知识点总结(2)(红外感应开关 与 继电器接法 模拟输入输出tone函数)

    ** Arduino入门小知识点总结(2)(红外感应开关 与 继电器) ** 1.关于电磁继电器的接法 说来惭愧,本是多么简单的一个问题,我用了约十万六千三百二十七次心跳(这梗懂得都懂)的时间,才查到 ...

最新文章

  1. 【网络编程】MarioTCP 流程图(一)
  2. python学习笔记目录
  3. macOS下nginx配合obs做推流直播.md
  4. 弦截法c语言程序,高数介质定理——弦截法求根代码实践(C语言)
  5. go语言学习---使用os.Args获取简单参数(命令行解析)
  6. PYTHON自动化Day3-列表/元组/切片/字典/字符串处理方法
  7. golang基本数据类型默认值
  8. c++如何对结构体作为形参设置默认值
  9. 【渝粤题库】广东开放大学 标准的研制与编制 形成性考核
  10. 系统和服务器的关系图,服务器与客户端关系图
  11. 大文件数据导出(后台执行,自动生成)
  12. mysql批量执行sql文件
  13. GitHack 源码分析
  14. 半部秘籍--分类、回归、集成与无监督
  15. 一元二次方程的c语言代码,一元二次方程求解程序完整代码
  16. UCF,基于用户的协同过滤算法
  17. tablewidget
  18. CSS中的边框与内边距外边距
  19. java是什么?好学吗?
  20. Ubuntu20.04 配置网卡信息

热门文章

  1. java中用spring boot连接oracle数据库
  2. WinFrom中TreeView中的应用
  3. 2014年中秋,该死的博古架+X酒架
  4. android自定义圆角进度条,Android自定义进度条的圆角横向进度条实例详解
  5. css盒模型content-box和border-box
  6. java中的holder类,SpringContextHolder工具类
  7. 技术人员的赚钱之道-11:钱是什么?钱能生钱吗?
  8. 【python】: 婴儿名字
  9. 作为iOS开发者,怎能不follow这52个牛人
  10. html5 弹性挂件,第五人格5款带有特殊动作的挂件,动作超有爱,佛系玩家必备...