Hibernate
主流 ORM 框架 Object Relation Mapping 对象关系映射,将⾯向对象映射成⾯向关系。
如何使⽤
1、导⼊相关依赖
2、创建 Hibernate 配置⽂件
3、创建实体类
4、创建实体类-关系映射⽂件
5、调⽤ Hibernate API 完成操作
具体操作
1、创建 Maven ⼯程,pom.xml
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.10.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
</dependencies>
2、hibernate.cfg.xml(resources资源目录下,名字可以重载,但是调用configuration时必须写上重载后的名字)
核⼼配置:session-factory
SessionFactory:针对单个数据库映射经过编译的内存镜像⽂件,将数据库转换为⼀个 Java 可以识别的镜像⽂件。
构建 SessionFactory ⾮常耗费资源,所以通常⼀个⼯程只需要创建⼀个 SessionFactory。
<?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>
<session-factory>
<!-- 数据源配置 -->
<property name="connection.username">root</property>
<property name="connection.password">199810</property>
<property
name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate?
useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC</property>
<!-- C3P0 -->
<property name="hibernate.c3p0.acquire_increment">10</property>
<property name="hibernate.c3p0.idle_test_period">10000</property>
<property name="hibernate.c3p0.timeout">5000</property>
<property name="hibernate.c3p0.max_size">30</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_statements">10</property>
<!-- 数据库⽅⾔ -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 打印SQL -->
<property name="show_sql">true</property>
<!-- 格式化SQL -->
<property name="format_sql">true</property>
<!-- 是否⾃动⽣成数据库 -->
<property name="hibernate.hbm2ddl.auto"></property>
</session-factory>
</hibernate-configuration>
3.创建实体类
package com.southwind.entity;
import lombok.Data;
import java.util.Set;
@Data
public class Customer {
private Integer id;
private String name;
//一个客户对应多个订单
private Set<Orders> orders;
}
package com.southwind.entity;
import lombok.Data;
@Data
public class Orders {
private Integer id;
private String name;
//一个订单对应一个客户
private Customer customer;
}
4、创建实体关系映射⽂件
people表与实体类People类的映射
package com.southwind.entity;
import lombok.Data;
@Data
public class People {
private Integer id;
private String name;
private Double money;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HeZVOWcr-1617146781087)(file:///C:\Users\Administrator\AppData\Roaming\Tencent\Users\1569235486\QQ\WinTemp\RichOle\26]315_M8N5T0BZKR`A%G.png)]
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.southwind.entity.People" table="people">
<!--主键配置--自增-->
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<generator class="identity"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<property name="money" type="java.lang.Integer">
<column name="money"></column>
</property>
</class>
</hibernate-mapping>
5、实体关系映射⽂件注册到 Hibernate 的配置⽂件中。
<!-- 注册实体关系映射⽂件 -->
<mapping resource="com/southwind/entity/People.hbm.xml"></mapping>
6、使⽤ Hibernate API 完成数据操作。
package com.southwind.Test;
import com.southwind.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class test {
@Test
public void test1(){
//创建一个Configuration
//配置文件名默认hibernate.cfg.xml,但是有方法重载,如果重命名,需要在下面手动添加上重新命名过的名字
Configuration configuration = new Configuration().configure("hibernate.xml");
//获取一个SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取session对象
Session session = sessionFactory.openSession();
//添加一条记录
People people = new People();
people.setName("张三");
people.setMoney(1000);
session.save(people);
session.beginTransaction().commit();
session.close();
}
}
7.pom.xml 中需要配置 resource。
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
Hibernate 级联操作
1、⼀对多关系
客户和订单:每个客户可以购买多个产品,⽣成多个订单,但是⼀个订单只能属于⼀个客户,所以客户是⼀,订单是多。
数据库中⼀的⼀⽅是主表,多的⼀⽅时候从表,通过主外键关系来维护。
⾯向对象中
package com.southwind.entity;
import lombok.Data;
import java.util.Set;
@Data
public class Customer {
private Integer id;
private String name;
//一个客户对应多个订单
private Set<Orders> orders;
}
package com.southwind.entity;
import lombok.Data;
@Data
public class Orders {
private Integer id;
private String name;
//一个订单对应一个客户
private Customer customer;
}
2、多对多关系
学⽣选课:⼀⻔课程可以被多个学⽣选择,⼀个学⽣可以选择多⻔课程,学⽣是多,课程也是多。
数据库中是通过两个⼀对多关系来维护的,学⽣和课程都是主表,额外增加⼀张中间表作为从表,两张主表和中间表都是⼀对多关系。
package com.southwind.entity;
import lombok.Data;
import java.util.Set;
@Data
public class Account {
private Integer id;
private String name;
private Set<Course> courses;
}
package com.southwind.entity;
import lombok.Data;
import java.util.Set;
@Data
public class Course {
private Integer id;
private String name;
private Set<Account> accounts;
}
Java 和数据库对于这两种关系的体现完全是两种不同的⽅式,Hibernate 框架的作⽤就是将这两种⽅式进⾏转换和映射。
Hibernate 实现⼀对多
Customer.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.southwind.entity.Customer" table="customer">
<!--主键配置--自增-->
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<generator class="identity"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--一对多关联Order-->
<set name="orders" table="orders">
<!--通过cid外键关联-->
<key column="cid"></key>
<one-to-many class="com.southwind.entity.Orders"></one-to-many>
</set>
</class>
</hibernate-mapping>
-
set 标签来配置实体类中的集合属性 orsers
-
name 实体类属性名
-
table 表名
-
key 外键
-
one-to-many 一对多 与集合泛型的实体类对应
多对一
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.southwind.entity.Orders" table="orders">
<!--主键配置-->
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<!--自增类型-->
<generator class="identity"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--多对一关联Customer-->
<many-to-one name="customer" class="com.southwind.entity.Customer" column="cid"></many-to-one>
</class>
</hibernate-mapping>
- many-to-one 配置实体类对应的对象属性
- name 属性名
- class 属性对应的类
- column 外键
需要在 Hibernate.xml 配置⽂件中进⾏注册
<!-- 注册实体关系映射⽂件 -->
<mapping resource="com/southwind/entity/Customer.hbm.xml"></mapping> <mapping resource="com/southwind/entity/Orders.hbm.xml"></mapping>
一对多测试
Hibernate API调用
package com.southwind.test;
import com.southwind.entity.Customer;
import com.southwind.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Test一对多 {
public static void main(String[] args) {
//加载配置,获取session对象
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//创建Customer对象
Customer customer = new Customer();
customer.setName("张三");
//创建Orders对象
Orders orders = new Orders();
orders.setName("订单1");
//实体类层建立关联关系--数据库中外键对应
orders.setCustomer(customer);
//保存到数据库中
session.save(customer);
session.save(orders);
//提交&关闭
session.beginTransaction().commit();
session.close();
}
}
多对多
Account.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.southwind.entity.Account" table="t_account">
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<generator class="identity"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--多对多是两个一对多set,table选择中间表-->
<set name="courses" table="account_course">
<!--account与中间表对应的外键是aid-->
<key column="aid"></key>
<!--通过aid找到cid找到对应的course表的信息,cid为course与中间表的外键-->
<many-to-many class="com.southwind.entity.Course" column="cid"></many-to-many>
</set>
</class>
</hibernate-mapping>
Course.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.southwind.entity.Course" table="t_course">
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<generator class="identity"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--多对多是两个一对多set,table选择中间表-->
<set name="accounts" table="account_course">
<!--course与中间表对应的外键是cid-->
<key column="cid"></key>
<!--通过cid找到aid找到对应的account表的信息,aid为account与中间表的外键-->
<many-to-many class="com.southwind.entity.Account" column="aid"></many-to-many>
</set>
</class>
</hibernate-mapping>
- name 实体类对应的集合属性名
- table 中间表名
- key 外键
- many-to-many 与集合泛型的实体类对应
- column 属性与中间表的外键字段名对应
注册 Hibernate 配置⽂件中
<mapping resource="com/southwind/entity/Account.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Course.hbm.xml"></mapping>
Hibernate API调用
package com.southwind.test;
import com.southwind.entity.Account;
import com.southwind.entity.Course;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import java.util.HashSet;
import java.util.Set;
public class Test3多对多 {
public static void main(String[] args) {
//加载配置,获取session对象
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//创建Count对象
Course course = new Course();
course.setName("Java");
//创建Account对象
Account account = new Account();
account.setName("张三");
//多对多,创建一个Course类的set集合保存course类
Set<Course> courses = new HashSet<>();
courses.add(course);
//实体类层建立关联关系--数据库中外键对应
account.setCourses(courses);
//数据库保存数据
session.save(course);
session.save(account);
//提交&关闭
session.beginTransaction().commit();
session.close();
}
}
Hibernate 延迟加载
延迟加载、惰性加载、懒加载
使⽤延迟加载可以提⾼程序的运⾏效率,Java 程序与数据库交互的频次越低,程序运⾏的效率⾼,
所以我们应该尽量减少 Java 程序与数据库的交互次数,Hibernate 延迟加载就很好的做到了这点。
客户和订单,当我们查询客户对象时,因为有级联设置,所以会将对应的订单信息⼀并查询出来,这样就需要发送两条 SQL 语句,分别查询客户信息和订单信息。
延迟加载的思路是:当我们查询客户的时候,如果没有访问订单数据,只发送⼀条 SQL 语句查询户信息,如果需要访问订单数据,则发送两条 SQLL。
延迟加载可以看作是⼀种优化机制,根据具体的需求,⾃动选择要执⾏的 SQL 语句数量。
⼀对多
1、查询 Customer,对 orders 进⾏延迟加载设置,在 customer.hbm.xml 进⾏设置,延迟加载默认开启。
<set name="orders" table="orders" lazy="true">
<key column="cid"></key>
<one-to-many class="com.southwind.entity.Orders"></one-to-many>
</set>
2、查询 Customer
package com.southwind.test;
import com.southwind.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Test4 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure("hibernate.xml");
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class,15);
//System.out.println(customer.orders);
System.out.println(customer);
session.close();
}
}
lazy 除了可以设置 true 和 false 之外,还可以设置 extra,extra 是⽐ true 更加懒惰的⼀种加载⽅式,或者说是更加智能的⼀种加载⽅式
no-proxy:当调⽤⽅法需要访问 customer 的成员变量时,发送 SQL 语句查询 Customer,否则不查询。
proxy:⽆论调⽤⽅法是否需要访问 customer 的成员变量,都会发送 SQL 语句查询 Customer。
Hibernate 配置⽂件
hibernate.xml
hbm.xml
Hibernate.xml
hibernate.xml 配置 Hibernate 的全局环境。
<?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>
<session-factory>
<!-- 数据源配置 -->
<property name="connection.username">root</property>
<property name="connection.password">199810</property>
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate? useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC</property>
<!-- C3P0 -->
<!--连接数不够时每次增加的数量-->
<property name="hibernate.c3p0.acquire_increment">10</property>
<!--设置失效时间/秒-->
<property name="hibernate.c3p0.idle_test_period">10000</property>
<!--设置超时时间/秒-->
<property name="hibernate.c3p0.timeout">5000</property>
<!--最大连接数-->
<property name="hibernate.c3p0.max_size">30</property>
<!--最小连接数-->
<property name="hibernate.c3p0.min_size">5</property>
<!--jdbc执行语句对象-->
<property name="hibernate.c3p0.max_statements">10</property>
<!-- 数据库⽅⾔ -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 打印SQL -->
<property name="show_sql">true</property>
<!-- 格式化SQL -->
<property name="format_sql">true</property>
<!-- 是否⾃动⽣成数据库 -->
<property name="hibernate.hbm2ddl.auto"></property>
<!--注册实体类关系映射文件-->
<mapping resource="com/southwind/entity/People.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Customer.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Orders.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Account.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Course.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
1、数据库的基本信息。
<!-- 数据源配置 -->
<property name="connection.username">root</property>
<property name="connection.password">199810</property>
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate? useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC</property>
2、集成 C3P0,设置数据库连接池信息。
<!-- C3P0 -->
<!--连接数不够时每次增加的数量-->
<property name="hibernate.c3p0.acquire_increment">10</property>
<!--设置失效时间/秒-->
<property name="hibernate.c3p0.idle_test_period">10000</property>
<!--设置超时时间/秒-->
<property name="hibernate.c3p0.timeout">5000</property>
<!--最大连接数-->
<property name="hibernate.c3p0.max_size">30</property>
<!--最小连接数-->
<property name="hibernate.c3p0.min_size">5</property>
<!--jdbc执行语句对象-->
<property name="hibernate.c3p0.max_statements">10</property>
3、Hibernate 基本信息。
<!-- 数据库⽅⾔ -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 打印SQL -->
<property name="show_sql">true</property>
<!-- 格式化SQL -->
<property name="format_sql">true</property>
<!-- 是否⾃动⽣成数据库 -->
<property name="hibernate.hbm2ddl.auto"></property>
- update:动态创建表,如果表存在,则直接使⽤,如果表不存在,则创建。
- create:⽆论表是否存在,都会重新创建。
- create-drop:初始化创建表,程序结束时删除表。
- validate:校验实体关系映射⽂件和数据表是否对应,不能对应直接报错。
4、注册实体关系映射⽂件。
<!--注册实体类关系映射文件-->
<mapping resource="com/southwind/entity/People.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Customer.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Orders.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Account.hbm.xml"></mapping>
<mapping resource="com/southwind/entity/Course.hbm.xml"></mapping>
实体关系映射⽂件
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.southwind.entity.Course" table="t_course">
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<generator class="identity"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--多对多是两个一对多set,table选择中间表-->
<set name="accounts" table="account_course">
<!--course与中间表对应的外键是cid-->
<key column="cid"></key>
<!--通过cid找到aid找到对应的account表的信息,aid为account与中间表的外键-->
<many-to-many class="com.southwind.entity.Account" column="aid"></many-to-many>
</set>
</class>
</hibernate-mapping>
hibernate-mapping 属性
- package:给 class 节点对应的实体类统⼀设置包名,此处设置包名,class 的 name 属性就可以省略包名。
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.southwind.entity">
</hibernate-mapping>
- schema:数据库 schema 的名称
- catalog:数据库 catalog 的名称
- default-cascade:默认的级联关系,默认为 none
- default-access:Hibernate ⽤来访问属性的策略
- default-lazy:指定了未明确注明 lazy 属性的 Java 属性和集合类,Hibernate 会采⽤什么样的加载⻛格,默认为 true
- auto-import:指定我们是否可以在查询语句中使⽤⾮全限定类名,默认为 true,如果项⽬中有两个同名的持久化类,最好在这两个类的对应映射⽂件中国配置为 false
class 属性
<class name="Course" table="t_course" schema="?" catalog="?" proxy="?" dynamic-update="true" dynamic-insert="true" where="id=6">
</class>
-
name:实体类名
-
table:数据表名
-
schema:数据库 schema 的名称,会覆盖 hibernate-mapping 的 schema
-
catalog:数据库 catalog 的名称,会覆盖 hibernate-mapping 的 catalog
-
proxy:指定⼀个接⼝,在延迟加载时作为代理使⽤
-
dynamic-update:动态更新
- Student表有{id=1,name=张三,age=22}一条属性,如果修改name为李四,没有设置动态更新情况下,会把id与age重新赋值一遍,即使id和age并没有被改变,但是实际上已经被重新赋值了,降低了效率,如果开启动态更新,就会自动判定是否与原来的一样,如果一样,就不会做改动,只更新需要改动的列值
-
dynamic-insert:动态添加
-
Student表有id,name,age三条属性,如果没有开启动态添加,插入id和name属性,hibernate会自动给age赋值null,而数据库本身就会自动给未赋值的添加null,当开启了动态添加时,hibernate就不会给age赋值null了
-
where:查询时给 SQL 添加 where 条件
-
例:
-
<class name="com.southwind.entity.People" table="people" where="id=6">
-
where条件就会自动加载hql语句的后面
-
id 属性
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<generator class="identity"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--多对多是两个一对多set,table选择中间表-->
<set name="accounts" table="account_course">
<!--course与中间表对应的外键是cid-->
<key column="cid"></key>
<!--通过cid找到aid找到对应的account表的信息,aid为account与中间表的外键-->
<many-to-many class="com.southwind.entity.Account" column="aid"></many-to-many>
</set>
- name:实体类属性名
- type:实体类属性数据类型
此处可以设置两种类型的数据:Java 数据类型或者 Hibernate 映射类型。
实体类的属性数据类型必须与数据表对应的字段数据类型⼀致:
int 对应 int,String 对应 varchar
如何进⾏映射?
Java 数据类型映射到 Hibernate 映射类型,再由 Hibernate 映射类型映射到 SQL 数据类型
Java —》Hibernate —〉SQL
-
column:数据表的主键字段名
-
generator:主键⽣成策略
1、hilo 算法
2、increment:Hibernate ⾃增
3、identity:数据库⾃增
4、native:本地策略,根据底层数据库⾃动选择主键的⽣成策略
5、uuid.hex 算法
6、select 算法
property 属性
- name:实体类的属性名
- column:数据表字段名
- type:数据类型
- update:该字段是否可以修改,默认为 true
- insert:该字段是否可以添加,默认为 true
- lazy:延迟加载策略
实体关系映射⽂件属性
1、inverse
Customer 和 Orders 是⼀对多关系,⼀个 Customer 对应多个 Orders,实体类中⽤⼀个 set 集合来表示对应的 Orders。
因为 Customer 和 Orders 都在维护⼀对多关系,所以会重复设置主外键约束关系。
如何避免这种情况?
1、在 Java 代码中去掉⼀⽅维护关系代码。
2、通过配置来解决。
<set name="orders" table="orders" lazy="extra" inverse="true">
<key column="cid"></key>
<one-to-many class="com.southwind.entity.Orders"></one-to-many>
</set>
inverse 属性是⽤来设置是否将维护权交给对⽅,默认是 false,不交出维护权,双⽅都在维护,将它设
置为 true,表示 Customer 放弃维护。
cascade:⽤来设置级联操作
实体关系映射⽂件中设置 cascade 值完成级联删除
<set name="orders" table="orders" lazy="extra" inverse="true"
cascade="delete">
<key column="cid"></key>
<one-to-many class="com.southwind.entity.Orders"></one-to-many>
</set>
package com.southwind.test;
import com.southwind.entity.Customer;
import com.southwind.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Test10 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure("hibernate.xml");
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class,19);
session.delete(customer);
session.beginTransaction().commit();
session.close();
}
}
Hibernate HQL
HQL:Hibernate Query Language,是 Hibernate 框架提供的⼀种查询机制,它和 SQL 类似,不同的是 HQL 是⾯向对象的查询语句,让开发者能够以⾯向对象的思想来编写查询语句,对 Java 编程是⼀种好友好的⽅式。
HQL 不能直接参与数据库的交互,中间层语⾔。
Java —》HQL —〉Hibernate —》SQL —〉DB
HQL 只能完成查询、修改、删除,新增是⽆法操作的。
1、查询对象
查询表中所有数据,⾃动完成对象的封装,返回 List 集合。
HQL 进⾏查询,from 关键字后⾯不能写表名,必须写表对应的实体类名。
@Test//hql语句查询
public void test2(){
//配置获取session
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//hql语句,面向对象的查询语言
String hql = "from com.southwind.entity.People";
Query query = session.createQuery(hql);
List<People> list = query.list();
list.forEach(System.out::println);
session.close();
}
2、分⻚查询
HQL 分⻚查询可以通过调⽤ query 的⽅法来完成。
1、setFirstResult() 设置起始下标
2、setMaxResults() 设置截取⻓度
@Test//测试分页查询
public void test3(){
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//hql语句
String hql = "from com.southwind.entity.People";
Query query = session.createQuery(hql);
//下标1开始查询,从0计数
query.setFirstResult(1);
//取3个结果出来
query.setMaxResults(3);
List<People> list = query.list();
for(People people:list){
System.out.println(people);
}
session.close();
}
3、where 条件查询
HQL 直接追加 where 关键字作为查询条件,与 SQL 没有区别。
@Test//测试where条件查询
public void test4(){
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
String hql = "from com.southwind.entity.People where id = 2";
Query query = session.createQuery(hql);
//query.list() 返回⼀个集合,此时集合中只有⼀个对象,通过下标 0 取出该对象。
People people = (People) query.list().get(0);
System.out.println(people);
session.close();
}
query.list() 返回⼀个集合,此时集合中只有⼀个对象,通过下标 0 取出该对象。
但是用query.list().get(0)调用一个不存在的id时会报错,这时用query.uniqueResult()方法调用就不会报错,返回一个null值
//当查询条件不存在时
String hql = "from com.southwind.entity.People where id = 0";
Query query = session.createQuery(hql);
People people = (People) query.uniqueResult();
System.out.println(people);
session.close();
4.模糊查询
查询名称包含 "三"的所有记录
@Test//模糊查询
public void test5(){
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//查询名字中带有"三"的信息
String hql = "from com.southwind.entity.People where name like '%三%' ";
Query query = session.createQuery(hql);
List<People> list = query.list();
list.forEach(System.out::println);
session.close();
}
5.排序查询
@Test//order by 排序
public void test(){
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//将查询的结果按照降序排序
String hql = "from com.southwind.entity.People order by id desc";
Query query = session.createQuery(hql);
query.list().forEach(System.out::println);
session.close();
}
6.查询实体对象的属性
@Test//查询实体对象的属性
public void test7(){
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//查询id为5的名字
String hql = "select name from com.southwind.entity.People where id = 5";
Query query = session.createQuery(hql);
String name = (String)query.uniqueResult();
System.out.println(name);
session.close();
}
7.占位符
@Test//占位符:?
public void test8(){
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
String hql = "from People where name = :name";
Query query = session.createQuery(hql);
query.setString("name","张三");
List<People> list = query.list();
list.forEach(System.out::println);
session.close();
}
8.级联查询
本质是把占位符换成对象代替外键
@Test//级联查询
public void test9(){
Configuration configuration = new Configuration().configure("hibernate.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//先得到Customer的结果
String hql1 = "from Customer where name = :name";
Query query1 = session.createQuery(hql1);
query1.setString("name","张三");
Customer customer = (Customer) query1.uniqueResult();
//把customer的结果作为Orders对象的条件
String hql2 = "from Orders where customer = :customer";
Query query2 = session.createQuery(hql2);
//调用setEntity()方法
query2.setEntity("customer",customer);
List<Orders> list = query2.list();
//重写Customer或Orders的toString方法,否则无限套娃
list.forEach(System.out::println);
session.close();
}