原视频内容以及资料来自 b 站:https://www.bilibili.com/medialist/play/ml1025729445/p1
hibernate 在 idea 中文件快速生成博客:https://blog.csdn.net/qq_34197553/article/details/77718925
具体操作
创建 Maven 工程,pom.xml
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!--jdbc-->
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--hibernate-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.15.Final</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
hibernate.cfg.xml
核心配置:session-factory
SessionFactory:针对单个数据库映射经过编译的内存镜像文件,将数据库转换为一个 Java 可以识别的。
构建 SessionFactory 非常小号资源,所以通常一个工程只需要创建一个 SessionFactory。
<?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.username">root</property>
<property name="connection.password">root</property>
<property name="connection.url">jdbc:mysql://localhost:3306/jt_db</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!--连接池 C3P0-->
<property name="hibernate.c3p0.acquire_increment">10</property>
<!--释放资源时间的限制-->
<property name="hibernate.c3p0.idle_test_period">1000</property>
<!--超时设置-->
<property name="hibernate.c3p0.timeout">5000</property>
<!--最大连接数-->
<property name="hibernate.c3p0.max_size">30</property>
<!--最小连接数-->
<property name="hibernate.c3p0.min_size">5</property>
<!--statements最大线程数-->
<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">update</property>
</session-factory>
</hibernate-configuration>
新建一个实体类:
@Data
public class User {
private Integer id;
private String username;
private String password;
}
创建关系映射文件 User.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>
<class name="com.tedu.entity.User" table="user" schema="jt_db">
<id name="id" column="id" type="java.lang.Integer">
<generator class="identity"></generator>
</id>
<property name="username" column="username" type="java.lang.String"/>
<property name="password" column="password" type="java.lang.String"/>
</class>
</hibernate-mapping>
实体关系映射文件注册到 hibernate 配置文件中
<mapping resource="User.hbm.xml"/>
创建测试类测试结果
public class Test {
public static void main(String[] args) {
//创建Configuration对象
Configuration configuration=new Configuration().configure();
System.out.println(configuration);
// 获取一个seesionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取session
Session session = sessionFactory.openSession();
User user=new User();
user.setUsername("王八");
user.setPassword("1024");
session.save(user);
// 开启事务
Transaction transaction = session.beginTransaction();
//提交事务
transaction.commit();
// 关闭
session.close();
sessionFactory.close();
}
}
Hibernate 级联操作
数据库的表结构
一对多
customer 表
orders 表
多对多
t_account 表
t_course 表
中间表 account_course
1.一对多的关系
客户和订单:每个客户可以购买多个产品,生成多个订单,但是一个订单只能属于-一个客户,所以客户是一,订单是多。数据库中一的
一 方是主表, 多的- -方时候从表,通过主外键关系来维护。
面向对象中
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class Customer {
private Integer id;
private String name;
private Set<Orders> ordersSet;
}
@Data
public class Orders {
private Integer id;
private String name;
private int cid;
private Customer customer;
}
hibernate 实现一对多
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>
<!--配置表信息-->
<class name="com.tedu.entity.Customer" table="customer" schema="jt_db">
<!--配置主键-->
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<!--主键自增-->
<generator class="identity"></generator>
</id>
<!--配置字段-->
<property name="name" column="name" type="java.lang.String"/>
<!--配置一对多的关系-->
<set name="ordersSet" table="orders">
<key column="cid"></key>
<!--一对多关系-->
<one-to-many class="com.tedu.entity.Orders"></one-to-many>
</set>
</class>
</hibernate-mapping>
- set 标签来配置实体类中的集合属性 ordersSet
- name 实体类属性名
- table 表名
- key 外键
- one-to-many 与集合泛型的实体类对应
Orders.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>
<class name="com.tedu.entity.Orders" table="orders" schema="jt_db">
<id name="id" column="id" type="java.lang.Integer">
<generator class="identity"></generator>
</id>
<property name="name" column="name" type="java.lang.String"/>
<many-to-one name="customer" class="com.tedu.entity.Customer" column="cid"></many-to-one>
</class>
</hibernate-mapping>
- many-to-one 配置实体类对应的对象属性
- name 属性名
- class 属性对应的类
- column 外键字段
在 Hibernate 配置文件进行注册
新建测试类
public class Test2 {
public static void main(String[] args) {
// 创建 Configuration
Configuration configuration=new Configuration().configure();
// 获取SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 获取 Session
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();
sessionFactory.close();
}
}
2、多对多关系
学生选课:一门课程可以被多个学生选择,-个学生可以选择多门课程,学生是多,课程也是多。
数据库中是通过两个一对多关系来维护的,学生和课程都是主表,额外增加一张中间表作为从表,两张主表和中间表都是一对多关系。
面向对象中
@Data
public class TAccount {
private int id;
private String name;
private Set<TCourse> courseSet;
}
@Data
public class TCourse {
private int id;
private String name;
private Set<TAccount> accountSet;
}
Hibernate 实现多对多
TAccount.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>
<class name="com.tedu.entity.TAccount" table="t_account" schema="jt_db">
<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 name="courseSet" table="account_course">
<key column="aid"></key>
<many-to-many class="com.tedu.entity.TCourse" column="cid"></many-to-many>
</set>
</class>
</hibernate-mapping>
TCourse.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>
<class name="com.tedu.entity.TCourse" table="t_course" schema="jt_db">
<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 name="accountSet" table="account_course">
<key column="cid"></key>
<many-to-many class="com.tedu.entity.TAccount" column="aid"></many-to-many>
</set>
</class>
</hibernate-mapping>
- name 实体类对应集合的属性名
- table 中间表
- key 外键
- many-to-many 与集合泛型的实体类对应
- clumn 属性雨中间表的外字段名对应
注入 Hibernate 配置文件
测试类
public class Test3 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
TAccount tAccoun = new TAccount();
tAccoun.setName("张三");
TCourse tCourse =new TCourse();
tCourse.setName("python");
Set<TCourse> tCourses=new HashSet<>();
tCourses.add(tCourse);
tAccoun.setCourseSet(tCourses);
session.save(tCourse);
session.save(tAccoun);
session.beginTransaction().commit();
session.close();
sessionFactory.close();
}
}
Hibernate 延迟加载
延迟加载、惰性加载、懒加载
使用延迟加载可以提高程序的运行效率, Java 程序与数据库交互的频次越低,程序运行的效率就越高,
所以我们应该尽量减少Java程序与数据库的交互次数,Hibernate 延迟加载就很好的做到了这一一点。
客户和订单,当我们查询客户对象时,因为有级联设置,所以会将对应的订单信息一并查询出来, 这样
就需要发送两条SQL语句,分别查询客户信息和订单信息。
延迟加载的思路是:当我们查询客户的时候,如果没有访问订单数据,只发送一条SQL语句查询客户信
息,如果需要访问订单数据,则发送两条SQL。.
延迟加载可以看作是一种优化机制,根据具体的需求,自动选择要执行的SQL语句数量。
一对多关系
首先修改两个 pojo 对象
@Getter
@Setter
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class Customer {
private Integer id;
private String name;
private Set<Orders> ordersSet;
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
@Getter
@Setter
public class Orders {
private Integer id;
private String name;
private int cid;
private Customer customer;
@Override
public String toString() {
return "Orders{" +
"name='" + name + '\'' +
", cid=" + cid +
'}';
}
}
1、查询Customer,对orders进行延迟加载设置,在customer.hbm.xml进行设置,延迟加载默认开启。
<!--配置一对多的关系-->
<set name="ordersSet" table="orders" lazy="true">
<key column="cid"></key>
<!--一对多关系-->
<one-to-many class="com.tedu.entity.Orders"></one-to-many>
</set>
2、查询 Customer
public class Test4 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class, 16);
System.out.println(customer);
}
}
查询 Orders
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class, 16);
System.out.println(customer.getOrdersSet());
3、将延迟加载关闭
测试代码
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class, 16);
System.out.println(customer);
lazy除了可以设置true和false之外,还可以设置extra, extra是比true更加懶惰的一种加载方式,或者说是更加智能的-种加载方式,通过例子看区别:
查询Customer对象,打印该对象对应的orders集合的长度
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class, 16);
System.out.println(customer.getOrdersSet().size());
也可以通过Orders来设置Customer的延迟加载,orders.hbm.xml 中进行设置。
<many-to-one name="customer" class="com.tedu.entity.Customer" column="cid" lazy="proxy"></many-to-one>
public class Test5 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Orders orders = session.get(Orders.class, 24);
System.out.println(orders);
}
}
查询 Costomer对象
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Orders orders = session.get(Orders.class, 24);
System.out.println(orders.getCustomer());
no-proxy:当调用方法需要访问customer的成员变量时,发送SQL语句查询Customer,否则不查询。
proxy:无论调用方法是否需要访问customer的成员变量,都会发送SQL语句查询Customer。
多对多查询
1.修改两个 pojo 对象
@Getter
@Setter
public class TAccount {
private int id;
private String name;
private Set<TCourse> courseSet;
@Override
public String toString() {
return "TAccount{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
@Setter
@Getter
public class TCourse {
private int id;
private String name;
private Set<TAccount> accountSet;
@Override
public String toString() {
return "TCourse{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
查询TCourse,加载对应的TAccount,默认延迟加载开启。
<set name="accountSet" table="account_course" lazy="true">
<key column="cid"></key>
<many-to-many class="com.tedu.entity.TAccount" column="aid"></many-to-many>
</set>
public class Test6 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
TCourse tCourse = session.get(TCourse.class, 4);
System.out.println(tCourse);
}
}
修改为 false
<set name="accountSet" table="account_course" lazy="false">
<key column="cid"></key>
<many-to-many class="com.tedu.entity.TAccount" column="aid"></many-to-many>
</set>
测试结果
查询TAccount,加载对应的TCourse,默认延迟加载开启。
<set name="courseSet" table="account_course" lazy="true">
<key column="aid"></key>
<many-to-many class="com.tedu.entity.TCourse" column="cid"></many-to-many>
</set>
public class Test7 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
TAccount tAccount = session.get(TAccount.class, 4);
System.out.println(tAccount);
}
}
Hibernate 配置文件
1.hibernate.cfg.xml
hibernate.xml配置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.username">root</property>
<property name="connection.password">root</property>
<property name="connection.url">jdbc:mysql://localhost:3306/jt_db</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!--连接池 C3P0-->
<property name="hibernate.c3p0.acquire_increment">10</property>
<!--释放资源时间的限制-->
<property name="hibernate.c3p0.idle_test_period">1000</property>
<!--超时设置-->
<property name="hibernate.c3p0.timeout">5000</property>
<!--最大连接数-->
<property name="hibernate.c3p0.max_size">30</property>
<!--最小连接数-->
<property name="hibernate.c3p0.min_size">5</property>
<!--statements最大线程数-->
<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">update</property>
<mapping resource="Customer.hbm.xml"/>
<mapping class="com.tedu.entity.Customer"/>
<mapping class="com.tedu.entity.Orders"/>
<mapping resource="Orders.hbm.xml"/>
<mapping class="com.tedu.entity.User"/>
<mapping resource="User.hbm.xml"/>
<mapping resource="Account.hbm.xml"/>
<mapping class="com.tedu.entity.Account"/>
<mapping class="com.tedu.entity.TAccount"/>
<mapping resource="TAccount.hbm.xml"/>
<mapping resource="TCourse.hbm.xml"/>
<mapping class="com.tedu.entity.TCourse"/>
</session-factory>
</hibernate-configuration>
- 数据库的基本信息
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.url">jdbc:mysql://localhost:3306/jt_db</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
- 集成C3p0,设置数据库连接信息
<!--连接池 C3P0-->
<property name="hibernate.c3p0.acquire_increment">10</property>
<!--释放资源时间的限制-->
<property name="hibernate.c3p0.idle_test_period">1000</property>
<!--超时设置-->
<property name="hibernate.c3p0.timeout">5000</property>
<!--最大连接数-->
<property name="hibernate.c3p0.max_size">30</property>
<!--最小连接数-->
<property name="hibernate.c3p0.min_size">5</property>
<!--statements最大线程数-->
<property name="hibernate.c3p0.max_statements">10</property>
- 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">update</property>
- update:动态创建表,如果表存在,则直接使用,如果不存在则创建。
- create:无论表是否存在,都会重新创建。
- create-drop:初始化创建表,程序结束后删除表。
- validate:校验实体关系映射文件和数据表是否对应,不能对应直接报错
- 注册实体关系映射文件
<mapping resource="Customer.hbm.xml"/>
<mapping class="com.tedu.entity.Customer"/>
<mapping class="com.tedu.entity.Orders"/>
<mapping resource="Orders.hbm.xml"/>
<mapping class="com.tedu.entity.User"/>
<mapping resource="User.hbm.xml"/>
<mapping resource="Account.hbm.xml"/>
<mapping class="com.tedu.entity.Account"/>
<mapping class="com.tedu.entity.TAccount"/>
<mapping resource="TAccount.hbm.xml"/>
<mapping resource="TCourse.hbm.xml"/>
<mapping class="com.tedu.entity.TCourse"/>
实体关系映射文件
<?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>
<!--配置表信息-->
<class name="com.tedu.entity.Customer" table="customer" schema="jt_db">
<!--配置主键-->
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<!--主键自增-->
<generator class="identity"></generator>
</id>
<!--配置字段-->
<property name="name" column="name" type="java.lang.String" />
<!--配置一对多的关系-->
<set name="ordersSet" table="orders" lazy="extra">
<key column="cid"></key>
<!--一对多关系-->
<one-to-many class="com.tedu.entity.Orders"></one-to-many>
</set>
</class>
</hibernate-mapping>
hibernate-mapping 属性
- package: 给class节点对应的实体类统一 设置包名,此处设置包名,class的name属性就可以省略包名。
- schema:数据库schema的名称
- catalog:数据库catalog的名称
- default-cascade:默认的级联关系,默认为none
- default-access: Hibernate 用来访问属性的策略
- default-lazy:指定了未明确注明lazy属性的Java属性和集合类,Hibernate 会采用什么样的加载风格,默认为true
- auto-import:指定我们是否可以在查询语句中使用非全限定类名,默认为true,如果项目中有两
个同名的持久化类,最好在这两个类的对应映射文件中配置为false
class 属性
- name:实体类名
- table:数据表名
- schema:数据库schema的名称,会覆盖hibernate-mapping的schema
- catalog:数据库catalog的名称,会覆盖hibernate-mapping的catalog
- proxy:指定一个 按口,在处迟加载时作为代理使用
- dynamic-update:动态更新
- dynamic-insert:动态添加
测试动态添加:dynamic-insert
测试代码
public class Test8 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
User user =new User();
user.setUsername("章泽天");
session.save(user);
session.close();
}
}
修改之前
<class name="com.tedu.entity.User" table="user" schema="jt_db" dynamic-insert="true">
修改之后
测试动态更新:dynamic-update
测试代码
public class Test8 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
User user = session.get(User.class, 5);
user.setPassword("66666");
session.update(user);
session.beginTransaction().commit();
session.close();
}
}
修改之前
修改之后
<class name="com.tedu.entity.User" table="user" schema="jt_db"
dynamic-update="true"
dynamic-insert="true">
- where:查询时给SQL 添加 where 条件
测试代码:
public class Test8 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
String hql = "from User";
Query query = session.createQuery(hql);
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
session.close();
}
}
测试结果之前
测试结果之后
<class name="com.tedu.entity.User" table="user" schema="jt_db"
dynamic-update="true"
dynamic-insert="true"
where="id=6"
>
id属性
- 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:实体类属性名
- type:实体类属性数据类型
- column:数据表的主键字段
- update:该字段是否可以修改,默认为true
- insert:该字段是否可以添加,默认为true
- lazy:延迟加载策略
实体关系映射文件属性
1、inverse
Customer和Orders是一对多关系,一个Customer对应多个Orders, 实体类中用一个set集合来表.
示对应的Orders。
测试代码:
public class Test9 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Customer customer = new Customer();
customer.setName("张三");
Orders orders1 = new Orders();
orders1.setName("订单1");
orders1.setCustomer(customer);
Orders orders2 = new Orders();
orders2.setName("订单2");
orders2.setCustomer(customer);
session.save(customer);
session.save(orders1);
session.save(orders2);
session.beginTransaction().commit();
session.close();
}
}
添加如下代码
Set<Orders> orders =new HashSet<>();
orders.add(orders1);
orders.add(orders2);
customer.setOrdersSet(orders);
因为Customer和Orders都在维护一对多关系,所以会重复设置主外键约束关系。
如何避免这种情况?
1、在Java代码中去掉一 方维护关系代码。
2、通过配置来解决。
<!--配置一对多的关系-->
<set name="ordersSet" table="orders" lazy="extra" inverse="true">
<key column="cid"></key>
<!--一对多关系-->
<one-to-many class="com.tedu.entity.Orders"></one-to-many>
</set>
inverse属性是用来设置是否将维护权交给对方,默认是false,不交出维护权,双方都在维护,将它设
置为true,表示Customer放弃维护。
cascade:用来设置级联操作
1.代码的方式实现级联的删除操作
public class Test10 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class, 20);
Iterator<Orders> iterator =customer.getOrdersSet().iterator();
while ((iterator.hasNext())){
session.delete(iterator.next());
}
session.delete(customer);
session.beginTransaction().commit();
session.close();
}
}
实体关系映射文件中设置cascade值完成级联删除。
<!--配置一对多的关系-->
<set name="ordersSet" table="orders" lazy="extra" inverse="true" cascade="delete">
<key column="cid"></key>
<!--一对多关系-->
<one-to-many class="com.tedu.entity.Orders"></one-to-many>
</set>
public class Test10 {
public static void main(String[] args) {
Configuration configuration =new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Customer customer = session.get(Customer.class, 21);
// Iterator<Orders> iterator =customer.getOrdersSet().iterator();
//
// while ((iterator.hasNext())){
// session.delete(iterator.next());
// }
session.delete(customer);
session.beginTransaction().commit();
session.close();
}
}
Hibernate HQL
HQL: Hibernate Query Language,是Hibernate框架提供的一种查询机制,它和SQL类似,不同的是HQL是面向对象的查询语句,让开发者能够以面向对象的思想来编写查询语句,对Java编程是一种
好友好的方式。
HQL不能直接参与数据库的交互,中间层语言。
Java-- HQL-- Hibernte— SQL-- DB
HQL只能完成查询、修改、删除,新增是无法操作的。
1、查询对象
查询表中所有数据,自动完成对象的封装,返回List集合。
HQL进行查询,from 关键字后面不能写表名,必须写表对应的实体类名。
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
String hql = "from User";
Query query = session.createQuery(hql);
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
session.beginTransaction().commit();
session.close();
2、分页查询
HQL分页查询可以通过调用query的方法来完成。
1、setFirstResult()设置起始下标
2、setMaxResults() 设置截取长度
// 分页查询
String hql = "from User";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(3);
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
3、where条件查询
HQL直接追加where关键字作为查询条件,与sQL没有区别。
query.list()返回-个集合,此时集合中只有一个对象,通过下标0取出该对象。
// where 条件查询语句
String hql = "from User where id = 5";
Query query = session.createQuery(hql);
User user = (User) query.list().get(0);
System.out.println(user);
查询不存在的id时不会抛出异常,而是返回一个 null 值
// where 条件查询语句
String hql = "from User where id = 5";
Query query = session.createQuery(hql);
User user = (User) query.uniqueResult();
System.out.println(user);
4、模糊查询
查询名称包含“章”的所有记录
// 模糊查询
String hql = "from User where username like '%章%'";
Query query = session.createQuery(hql);
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
5、order by
按照id进行排序
//排序
String hql = "from User order by id desc ";
Query query = session.createQuery(hql);
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
asc是生序排列,desc 是降序排列。
6、查询实体对象的属性
// 查询属性
String hql ="select username from User where id= 6 ";
Query query = session.createQuery(hql);
String user = (String) query.uniqueResult();
System.out.println(user);
7、查询总数
// 查询总数
String hql = "select count(*) from User ";
Query query = session.createQuery(hql);
Long count = (Long) query.uniqueResult();
System.out.println(count);
8、占位符
String hql = "from User where username=:name";
Query query = session.createQuery(hql);
query.setString("name", "章泽天");
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
8、级联查询
String hql1 = "from Customer where name = :name";
Query query1 = session.createQuery(hql1);
query1.setString("name","张三");
Customer customer = (Customer) query1.uniqueResult();
String hql2 = "from Orders where customer = :customer";
Query query2 = session.createQuery(hql2);
query2.setEntity("customer", customer);
List<Orders> list = query2.list();
for (Orders orders : list) {
System.out.println(orders);
}