Hibernate是一种ORM框架,全称为 Object_Relative DateBase-Mapping,在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象!
ORM思想 对象关系映射
Hibernate入门案例
hibernate.cfg.xml配置
<?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>
<!-- session对象 连接数据库 操作数据库-->
<!--数据库方言-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!--驱动-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!--url-->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/crm_hibernate</property>
<!--用户名-->
<property name="hibernate.connection.username">root</property>
<!--密码-->
<property name="hibernate.connection.password">lily</property>
<!-- 显示执行的SQL语句 把你的SQL语句以一行的行输出到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化SQL语句 格式化后进行多行展示 -->
<property name="hibernate.format_sql">true</property>
<!--引入实体类的映射文件Customer.hbm.xml -->
<mapping resource="com/minimax/code/entity/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
在idea中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>
<property name="connection.url">jdbc:mysql://localhost:3306/crm_hibernate</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- <property name="connection.username"/> -->
<!-- <property name="connection.password"/> -->
<property name="connection.username">root</property>
<property name="connection.password">lily</property>
<!-- DB schema will be updated if needed -->
<!-- <property name="hbm2ddl.auto">update</property> -->
<mapping resource="com/minimax/code/entity/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
实体类Customer
package com.minimax.code.entity;
public class Customer {
private Long id; // '客户编号(主键)',
private String name; // '客户名称(公司名称)',
private String source; // '客户信息来源',
private String industry; // '客户所属行业',
private String level; // '客户级别',
private String phone; // '固定电话',
private String mobile; // '移动电话',
//有参构造,无参构造,get/set方法
}
实体类对应的映射文件Customer.hbm.xml
<?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>
<!--
配置表与类的映射
name 配置类的名称
table 表名(数据库概念为了和程序概念加以区分数据库中的对象都要大写)
-->
<class name="com.minimax.code.entity.Customer" table="CST_CUSTOMER" >
<!-- 属性与字段的配置 -->
<!-- 主键 -->
<id name="id" column="cust_id">
<!-- 主键自增策略 -->
<!-- mysql 支持主键自增 -->
<!-- hibernat让数据库自己决定主键的生成方法 因为mysql是自增的所以可以配置该属性 -->
<generator class="native"/>
</id>
<!--
普通字段
type="java.lang.String"
type="string"
如果类型映射正确是可以不用指定的
-->
<property name="name" column="cust_name" />
<property name="source" column="cust_source" />
<property name="industry" column="cust_industry" />
<property name="level" column="cust_level" />
<property name="phone" column="cust_phone" />
<property name="mobile" column="cust_mobile" />
</class>
</hibernate-mapping>
测试类Test.java
package com.minimax.code.test;
import com.minimax.code.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Test {
public static void main(String[] args) {
// 获取数据库连接 session-->sessionFacotry-->hibernate-configuration
// 创建configuration对象加载XML
Configuration cfg = new Configuration();
// 加载XML
cfg.configure();
// 创建session工厂类
SessionFactory sf = cfg.buildSessionFactory();
// 创建session对象 == conn + ps
Session session = sf.openSession();
// 添加操作 创建添加对象
Customer cus = new Customer();
cus.setIndustry("努力学习");
cus.setLevel("紫色");
cus.setMobile("1351245678");
cus.setName("我是一个hibernate案例");
cus.setPhone("010-12345678");
cus.setSource("网络");
// 开启事务
Transaction transaction = session.beginTransaction();
try {
session.save(cus);
transaction.commit();
System.out.println("添加成功");
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
以上是一个hibernage的入门案例
get()和load()
load() 延迟加载 懒加载
懒加载在加载一个实体的时候,不会马上从数据库中加载,即从数据库中加载到内存。而急加载在加载一个实体时,会立即从数据库中查询,与其关联的类也会被同时查询。
急加载就会很快,因为在第一次加载的时候,已经帮我们全部加载好了。而懒加载则会相对慢一些,因为在我门需要查询的时候,它才会执行sql操作。
所以懒加载的优点是占用内存小,执行速度慢;急加载是执行速度快,占用内存高
hibernate的get()和 load()方法在执行的时候又很大的区别,
执行get()方法会把所有的基本数据全部加载,
而load()方法在懒加载中只会加载ID属性,所有的ID属性,其他的非ID属性的操作都不会执行,当我们需要查询默写具体的数据是才会真的执行sql操作,因为懒加载的有效期是在一个session中,所以今天我们在关闭了session的情况下会报错,因为Hibernate尝试通过当前session发sql查询,但发现session已经关闭,这样就会发出no session的异常 。
我们可以吧加载方式变成急加载或者不关闭session。
Hibernate的持久化类和对象标示符
持久化类 : 持久化 某个java的普通类与表建立映射关系之后
规范
- 持久化类需要无参的构造
- 属性都是私有的 提供get set方法
- 持久化类的属性都是包装类型 null int(0) Integer(null)
- 持久化类中必须有一个属性与主键字段对应
- implements Serializable
对象标识符
- OID 表的主键ID --> 程序里被标记成<id>标签里面的属性
- 1) Hibernate用于区分两个对象的唯一途径
- 2) 对象标示符可以帮助session完成查询性能的优化
Hibernate主键自增策略:
- native : 让数据库自己决定主键如何生存适合于能主键自增的数据(mysql sqlserver)
- sequence : 使用序列来生成主键,有的数据库不支持主键自增(Oracle)
- identity : 采用数据库的主键自增来生成主键(mysql,sqlserver,DB2)
uuid : 根据128位数据算法生成32为的一个字母+数字的字符串用来标识主键
uuid : 当你一个程序使用两个数据库的时候必须使用UUID作为同名表的主键ID; 数据1 数据2 userinfo (1 2 3 4) (1 2 3 4)
Hibernate一级缓存
hibernate一级缓存(session缓存)
缓存 : 临时存储硬盘数据到内存中的一项技术;
程序运行在内存里 所以当读取数据的时候 内存读内存 内存读硬盘快
Hibernate为了提升查询性能也进行了缓存操作-->Session
Session的一级缓存 是Hibernate用于进行数据库与程序之间沟通的一个桥;
当程序完成持久化操作的时候Hibernate会通过Session把该对象与相对应的数据库中的数据关联到一起;例如:当查询表中一条数据是,hibernate会先存在session中再返回,当再次查询的时候会先去缓存中查找,没有再去查询数据库
快照机制 :
说明了session不光可以缓存数据库中的数据,还可以管理数据库中的数据,但是要注意快照机制只能简化更新操作;
缓存与快照机制保证了数据库的简化及性能提升操作;当session遇到commit是,会拿自己的缓存数据去和数据库对比,当发现不一样时,会更新数据库的数据(强制性的)
Hibernate管理java对象的三种状态
Hibernate管理Java对象的时候因为根据数据库数据对应于session管理不同分为三种状态
- 持久化 : 数据库有数据对应 被session管理
- 瞬时对象 : 数据库没有数据对应 session不管理
- 游离状态 : 数据库有数据对应 但是session不管理
操作
- 添加的一定是瞬时的
- 更新和修改的一定是持久的
Hibernate
表与表之间 多对多 多对一 一对一
<mapping resource="com/minimax/entity/Customer.hbm.xml"/> 引入实体类配置文件 //多对多 <set name="roles" table="sys_user_role"> <key column="user_id" /> <many-to-many class="com.minimax.entity.RoleInfo" column="role_id" /> </set> //多对一 <many-to-one lazy="false" name="cus" class="com.minimax.entity.Customer" column="lkm_cust_id"/> <!-- 配置set集合 --> <!-- cascade="all" 代表当添加一的一方的时候 级联添加多的一方 更新和删除走同样的操作 一的一方 添加 或者 删除的时候 同步操作多的一方 cascade="save" cascade="save-update" cascade="none" 不级联 save-update 数据库如果村存在主外键还删除不了 如果程序操作数据库那么数据库除主键约束外是不允许有其他约束的 lazy="true" 默认延迟加载 --> <set name="mans" inverse="true" cascade="all" lazy="extra"> <!-- 一个外键因为实体的摆放位置不同所以才有的两种关系 说白了 多对一 和 一对多 都是主外键关系 --> <key column="lkm_cust_id" /> <one-to-many class="com.itheima.entity.LinkMan"/> </set>
Hibernate注解配置实体类
@Entity @Table(name="cst_customer")//配置和数据库对应的表 public class Customer implements Serializable { @Id//主键Id @Column(name="cust_id")//配置和数据库表对应的字段 @GeneratedValue(strategy=GenerationType.IDENTITY) private Long cid;// '客户编号(主键)', @Column(name="cust_name") private String cname; // '客户名称(公司名称)', @Transient // private String industry; // '客户所属行业',
@Entity
作用:指定当前类是实体类。写上此注解用于创建SessionFactory/EntityManager时,加载映射配置
@Table
作用:制定实体类与表之间的对应关系
属性:name:制定数据库表的名称
@Id
作用:指定当前字段是主键
@GeneratedValue
作用:指定主键的生成方式
属性:strategy:指定主键生成策略。
JPA支持四种生成策略
IDENTITY:主键由数据库自动生成(主要是自动增长型)
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持数列@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="payablemoney_seq") @SequenceGenerator(name="payablemoney_seq",sequenceName="seq_payment") name:表示该表主键生成策略名称,它被引用在@GeneratedValue中设置对的generator值中。 sequenceName:属性表示生成策略用到的数据库序列名称
AUTO:主键由程序控制
TABLE:使用一个特定的数据库表格来保存主键(了解)
@Column
作用:指定实体类属性和数据库表之间的对应关系
属性:name:执行数据库的列名称
unique:是否唯一
nullable:是否可以为空
inserttable:是否可以插入
updateable:是否可以更新
columnDefinition:定义建表时创建此列的DDL
secondaryTable:从表名。如果此列不建在主标上(默认建在主表),改属性定义该列所在的从表的名字
一对多注解配置
@OneToMany
作用:建立一对多的关系映射
属性:
targetEntityClass:指定多的多方的类的字节码
mappedBy:指定从表实体类中引用主表对象的名称
cascade:指定要使用的级联操作
fetch:指定是否采用延迟加载
orphanRemoval:是否使用孤儿删除
@ManyToOne
作用:建立多对一的关系
属性:
targetEntityClass:指定一的一方的类的字节码
cascade:指定要使用的级联操作
fetch:指定是否采用延迟加载
optional:关联是否可选。如果设置为false,则必须始终存在非空关系。
orphanRemoval:是否使用孤儿删除
@JoinColumn
作用:用于定义主键字段和外键字段的对应关系
属性:
name:指定外键字段名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一
nullable:是否允许为空,默认值允许
insertable:是否允许插入,默认值允许
updatable:是否允许更新,默认值允许
columnDefinition:列的定义信息Customer类 @OneToMany(targetEntity=LinkMan.class,mappedBy="customer") private Set<LinkMan> linkmans = new HashSet<LinkMan>(); LinkMan类 @ManyToOne(targetEntity=Customer.class) @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
多对多关系映射
@ManyToMany
作用:
用于映射多对多关系
属性:
cascade:配置级联操作
fetch:配置是否采用延迟加载
targetEntity:配置目标实体类,映射多对多的时候不用写
@JoinTable
作用:
针对中间表的配置
属性:
name:配置中间表的名称
joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段
inverseJoinColumn:中间表的外键字段关联对方标的主键字段SysUser类 @ManyToMany(mappedBy="users") private Set<SysRole> roles = new HashSet<SysRole>(); SysRole类 @ManyToMany @JoinTable(name="user_role_rel",//中间表的名称 //中间表user_role_rel字段关联sys_role表的主键字段role_id joinColumns={@JoinColumn(name="role_id",referencedColumnName="role_id")}, //中间表user_role_rel字段关联sys_user表的主键user_id inverseJoinColumn={@JoinColumn(name="user_id",referencedColumnName="user_id")} ) private Set<SysUser> users = new HashSet<SysUser>();