Hibernate

主流ORM框架Object Relation Mapping对象关系映射,将面向对象映射成面向关系。


如何使用


1、导入相关依赖
2、创建Hibernate配置文件
3、创建实体类
4、创建实体类-关系映射文件
5、调用Hibernate API完成操作

具体操作

1、创建 Maven工程,在pom.xml中导入依赖

    <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.4.10.Final</version></dependency>

2、在resources下创建hibernate.cfg.xml文件,并配置其相关信息

在resources下创建hibernate.cfg.xml文件

核心配置: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://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory><!-- Hibernate 连接数据库的基本信息 --><property name="connection.username">root</property><property name="connection.password">Wrw156970</property><property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property><property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property><!-- 配置 C3P0 数据源 --><!-- 连接池不够时,新增10个 --><property name="hibernate.c3p0.acquire_increment">10</property><!-- 失效时间 --><property name="hibernate.c3p0.idle_test_period">2000</property><!-- 超时时间 --><property name="hibernate.c3p0.timeout">2000</property><!-- 最大连接数 --><property name="hibernate.c3p0.max_size">10</property><!-- 最小连接数 --><property name="hibernate.c3p0.min_size">5</property><!-- 执行最大连接数 --><property name="hibernate.c3p0.max_statements">10</property><!-- Hibernate 的基本配置 --><!-- Hibernate 使用的数据库方言 --><property name="dialect">org.hibernate.dialect.MySQLDialect</property><!-- 运行时是否打印 SQL --><!-- <property name="show_sql">true</property> --><property name="hibernate.show_sql">true</property><!-- 运行时是否格式化 SQL --><!--        <property name="format_sql">true</property>--><property name="hibernate.format_sql">true</property><!-- 生成数据表的策略 --><!-- <property name="hbm2ddl.auto">update</property>--><!-- 加载Hibernate时,验证数据库表结构与Hibernate映射的结构是否匹配。如果不匹配,会抛出异常--><property name="hibernate.hbm2ddl.auto">validate</property></session-factory></hibernate-configuration>

3、创建实体类

package org.example.entity;import lombok.Data;@Data
public class Orders {private Integer id;private String name;private Customer customer;
}
package org.example.entity;import lombok.Data;import java.util.Set;@Data
public class Customer {private Integer id;private String name;private Set<Orders> orders;
}

4、创建实体关系映射文件

package org.example.entity;import lombok.Data;@Data
public class People {private Integer id;private String name;private Double money;
}

类映射文件名为类名.hbm.xml,如下面文件名为People.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="org.example.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.Double"><column name="money"></column></property></class></hibernate-mapping>

 5、实体关系映射文件注册到Hibernate 的配置文件中。

<!-- 注册实体关系映射文件 -->
<mapping resource="org/example/entity/People.hbm.xml"></mapping>

6、使用Hibernate Api完成数据操作。

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//设置添加信息People people = new People();people.setName("张三");people.setMoney(1000.0);//添加session.save(people);//提交事务session.beginTransaction().commit();//关闭sessionsession.close();}
}

7、pom.xml 中需要配置 resource。

  <!-- 允许读取src/main/java路径下的xml文件 --><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource></resources></build>

其完整项目结构

Hibernate 级联操作

1、一对多关系

客户和订单:每个客户可以购买多个产品,生成多个订单,但是一个订单只能属于一个客户,所以客户是一,订单是多。

数据库中一的一方是主表,多的一方是从表,通过主外键关系来维护

面向对象中

package org.example.entity;import lombok.Data;import java.util.Set;@Data
public class Customer {private Integer id;private String name;private Set<Orders> orders;
}
package org.example.entity;import lombok.Data;@Data
public class Orders {private Integer id;private String name;private Customer customer;
}

2、多对多关系

学生选课:一门课程可以被多个学生选择,一个学生可以选择多门课程,学生是多,课程也是多。

数据库中是通过两个一对多关系来维护的,学生和课程都是主表,额外增加一张中间表作为从表,两张主表和中间表都是一对多关系。

面向对象中

package org.example.entity;import lombok.Data;import java.util.Set;@Data
public class Account {private Integer id;private String name;private Set<Course> courses;
}
package org.example.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 实现一对多

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping><class name="org.example.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><set name="orders" table="orders"><key column="cid"></key><one-to-many class="org.example.entity.Orders"></one-to-many></set></class>
</hibernate-mapping>
  • set 标签配置实体类中的集合属性 orders
  • name 实体类属性名
  • table 表名
  • key 外键
  • one-to-many 与集合泛型的实体类对应
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping><class name="org.example.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><many-to-one name="customer" class="org.example.entity.Customer" column="cid"></many-to-one></class>
</hibernate-mapping>
  •  many-to-one 配置实体类对应
  • name 属性名
  • class 属性对应的类
  • column 外键

需要在 Hibernate 配置文件中进行注册 

<!-- 注册实体关系映射文件 -->
<mapping resource="org/example/entity/Customer.hbm.xml"></mapping>
<mapping resource="org/example/entity/Orders.hbm.xml"></mapping>

一对多

Hibernate Api

package org.example;import org.example.entity.Customer;
import org.example.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test2 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//创建 CustomerCustomer customer = new Customer();customer.setName("张三");//创建 OrdersOrders orders = new Orders();orders.setName("订单1");//建立关联关系orders.setCustomer(customer);//保存session.save(customer);session.save(orders);//提交事务session.beginTransaction().commit();//关闭sessionsession.close();}
}

一对多完整项目结构

Hibernate 实现多对多

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping><class name="org.example.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 name="courses" table="account_course"><key column="aid"></key><many-to-many class="org.example.entity.Course" column="cid"></many-to-many></set></class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping><class name="org.example.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 name="accounts" table="account_course"><key column="cid"></key><many-to-many class="org.example.entity.Account" column="aid"></many-to-many></set></class>
</hibernate-mapping>
  • name 实体类对应的集合属性名
  • table 中间表名
  • key 外键
  • many-to-many 与集合泛型的实体类对应
  • column 属性与中间表的外键字段名对应

注册 Hibernate 配置文件中

<!-- 注册实体关系映射文件 -->
<mapping resource="org/example/entity/Account.hbm.xml"></mapping>
<mapping resource="org/example/entity/Course.hbm.xml"></mapping>

Hibernate Api

package org.example;import org.example.entity.Account;
import org.example.entity.Course;
import org.example.entity.Customer;
import org.example.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;import java.util.HashSet;
import java.util.Set;/*** @author 王润伟* @date 2024年05月26日 2:03*/
public class Test3 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Course course = new Course();course.setName("java");Account account = new Account();account.setName("张三");Set<Course> courses = new HashSet<Course>();courses.add(course);account.setCourses(courses);session.save(course);session.save(account);//提交事务session.beginTransaction().commit();//关闭sessionsession.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="org.example.entity.Orders"></one-to-many>
</set>

2、查询Customer

查询customer主表属性结果,只执行一条SQL

package org.example;import org.example.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test4 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Customer customer = session.get(Customer.class, 12);System.out.println(customer);//关闭sessionsession.close();}
}

查询customer下关联的次表Orders结果,执行两条SQL

package org.example;import org.example.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test4 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Customer customer = session.get(Customer.class, 12);System.out.println(customer.getOrders());//关闭sessionsession.close();}
}

去掉延迟加载,查询customer主表也会执行两条

<set name="orders" table="orders" lazy="false"><key column="cid"></key><one-to-many class="org.example.entity.Orders"></one-to-many>
</set>
package org.example;import org.example.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test4 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Customer customer = session.get(Customer.class, 12);System.out.println(customer);//关闭sessionsession.close();}
}

 lazy除了可以设置true和false之外,还可以设置extra,extra是比 true更加懒惰的一种加载方式,或者说是更加智能的一种加载方式,通过例子看区别:

查询Customer对象,打印该对象对应的orders集合的长度

设置lazy为true

package org.example;import org.example.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test4 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Customer customer = session.get(Customer.class, 12);System.out.println(customer.getOrders().size());//关闭sessionsession.close();}
}

查询结果会先查询次表数据,再统计数量,查询SQL数量统计语句复杂

设置lazy为extra

<set name="orders" table="orders" lazy="extra"><key column="cid"></key><one-to-many class="org.example.entity.Orders"></one-to-many>
</set>

查询结果用count统计次表查询的行数,大大简化SQL,查询效率增强

也可以通过Orders 来设置Customer的延迟加载,orders.hbm.xml中进行设置

这里azy设置为proxy,即启用懒加载

<many-to-one name="customer" class="org.example.entity.Customer" column="cid" lazy="proxy"></many-to-one>
package org.example;import org.example.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test5 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Orders orders = session.get(Orders.class, 4);System.out.println(orders);//关闭sessionsession.close();}
}

查询结果只执行一次SQL语句

查询orders表下的关联属性tcustomer,执行两次SQL语句

package org.example;import org.example.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test5 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Orders orders = session.get(Orders.class, 4);System.out.println(orders.getCustomer());//关闭sessionsession.close();}
}

no-proxy:当调用方法需要访问customer的成员变量时,发送SQL语句查询Customer,否则不查询。

proxy:无论调用方法是否需要访问customer的成员变量,都会发送SQL语句查询Customer。

多对多

查询Course,加载对应的Account,默认延迟加载开启,其实现结果跟一对多,一那方使用方式一致,就是<set>标签那方,这里就不做演示。

注意:当级联关系查询时会出现查询无线循环然后报错,这是因为两个关系表之间映射的对象的toString方法彼此包含关联的对象,这时查询就陷入循环,反复查询关联的表信息。

解决方法:重新toString方法,去掉关联对象属性,把@Data注解换成@Getter和@Setter。

 Hibernate 配置文件

  • hibernate.cfg.xml
  • hbm.xml

Hibernate.cfg.xml 

hibernate.xml配置Hibernate的全局环境。

1、数据库的基本信息。

<?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><!-- Hibernate 连接数据库的基本信息 --><property name="connection.username">root</property><property name="connection.password">Wrw156970</property><property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property><property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property><!-- 配置 C3P0 数据源 --><!-- 连接池不够时,新增10个 --><property name="hibernate.c3p0.acquire_increment">10</property><!-- 失效时间 --><property name="hibernate.c3p0.idle_test_period">2000</property><!-- 超时时间 --><property name="hibernate.c3p0.timeout">2000</property><!-- 最大连接数 --><property name="hibernate.c3p0.max_size">10</property><!-- 最小连接数 --><property name="hibernate.c3p0.min_size">5</property><!-- 执行最大连接数 --><property name="hibernate.c3p0.max_statements">10</property><!-- Hibernate 的基本配置 --><!-- Hibernate 使用的数据库方言 --><property name="dialect">org.hibernate.dialect.MySQLDialect</property><!-- 运行时是否打印 SQL --><property name="hibernate.show_sql">true</property><!-- 运行时是否格式化 SQL --><property name="hibernate.format_sql">true</property><!-- 生成数据表的策略 --><property name="hbm2ddl.auto">update</property><!-- 注册实体关系映射文件 --><mapping resource="org/example/entity/People.hbm.xml"></mapping><mapping resource="org/example/entity/Customer.hbm.xml"></mapping><mapping resource="org/example/entity/Orders.hbm.xml"></mapping><mapping resource="org/example/entity/Account.hbm.xml"></mapping><mapping resource="org/example/entity/Course.hbm.xml"></mapping></session-factory></hibernate-configuration>

1、数据库的基本信息

<property name="connection.username">root</property>
<property name="connection.password">Wrw156970</property>
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>

2、集合C3P0,设置数据库连接池信息。

<!-- 连接池不够时,新增10个 -->
<property name="hibernate.c3p0.acquire_increment">10</property>
<!-- 失效时间 -->
<property name="hibernate.c3p0.idle_test_period">2000</property>
<!-- 超时时间 -->
<property name="hibernate.c3p0.timeout">2000</property>
<!-- 最大连接数 -->
<property name="hibernate.c3p0.max_size">10</property>
<!-- 最小连接数 -->
<property name="hibernate.c3p0.min_size">5</property>
<!-- 执行最大连接数 -->
<property name="hibernate.c3p0.max_statements">10</property>

3、Hibernate 基本信息。

<!-- 运行时是否打印 SQL -->
<property name="hibernate.show_sql">true</property>
<!-- 运行时是否格式化 SQL -->
<property name="hibernate.format_sql">true</property>
<!-- 生成数据表的策略 -->
<property name="hbm2ddl.auto">update</property>
  • update:动态创建表,如果表存在,则直接使用,如果表不存在,则创建,一般使用此属性。
  • create:无论表是否存在,都会重新创建。
  • create-drop:初始化创建表,程序结束时删除表。
  • validate:校验实体关系映射文件和数据表是否对应,不能对应直接报错。

4、注册实体关系映射文件 

<!-- 注册实体关系映射文件 -->
<mapping resource="org/example/entity/People.hbm.xml"></mapping>
<mapping resource="org/example/entity/Customer.hbm.xml"></mapping>
<mapping resource="org/example/entity/Orders.hbm.xml"></mapping>
<mapping resource="org/example/entity/Account.hbm.xml"></mapping>
<mapping resource="org/example/entity/Course.hbm.xml"></mapping>

实体关系映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping><class name="org.example.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 name="accounts" table="account_course"><key column="cid"></key><many-to-many class="org.example.entity.Account" column="aid"></many-to-many></set></class>
</hibernate-mapping>

hibernate-mapping 属性 

  • package: 给 class 节点对应的实体类统一设置包名,此处设置包名,class 的 name 属性就可以省略包名。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.example.entity"><class name="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 name="accounts" table="account_course"><key column="cid"></key><many-to-many class="Account" column="aid"></many-to-many></set></class>
</hibernate-mapping>
  • 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 的使用

未使用时执行插入部分属性的效果

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test6 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();People people = new People();people.setName("李四");session.save(people);//关闭sessionsession.close();}
}

这里只设置 name 的值,没有设置 money 的值,而执行的 SQL 语句却包含新增 money 这项。

 

在 class 标签设置 dynamic-insert 为 true

<class name="org.example.entity.People" table="people" dynamic-insert="true">
</class>

 使用时执行插入部分属性的效果,发现新增了设置值的name属性

dynamic-update 的使用 

未使用时执行更新部分属性的效果

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test7 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();People people = session.get(People.class,1);people.setMoney(1999.0);//更新session.update(people);session.beginTransaction().commit();//关闭sessionsession.close();}
}

这里只修改money属性,执行更新语句时却更新全部属性

 在 class 标签设置 dynamic-update 为 true

    <class name="org.example.entity.People" table="people" dynamic-update="true"></class>

使用时执行部分属性更新的效果,发现只更新了修改的 money 属性

  • where:查询时给SQL添加where条件 

 查询某表所有数据具体实现

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;import java.util.List;public class Test8 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//查询people表的所有数据String hql = "from People";Query query = session.createQuery(hql);List<People> peoples = query.list();for (People p : peoples) {System.out.println(p);}session.beginTransaction().commit();//关闭sessionsession.close();}
}

查询结果为指定表的所有数据 

在查询的映射文件的 class 标签中添加 where 属性,设置其筛选条件,这里我设置其值为 id=2

<class name="org.example.entity.People" table="people" where="id=2">
</class>

 查询结果为 id=2 的数据

 

id属性

  • name:实体类属性名
  • type:实体类属性数据类型

此处可以设置两种类型的数据:Java 数据类型或者 Hibernate 映射类型。实体类的属性数据类型必须与数据表对应的字段数据类型一致:

int 对应 int,String 对应 varchar

如何进行映射?

Java 数据类型映射到Hibernate映射类型,再由Hibernate 映射类型映射到 SQ L数据类型 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 对象和 Customer.hbm.xml 映射文件

package org.example.entity;import lombok.Data;
import lombok.Getter;
import lombok.Setter;import java.util.Set;@Getter
@Setter
public class Customer {private Integer id;private String name;private Set<Orders> orders;@Overridepublic String toString() {return "Customer{" +"id=" + id +", name='" + name + '\'' +'}';}
}

Customer.hbm.xml 中使用 set 标签来配置映射关系。 

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping><class name="org.example.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><set name="orders" table="orders" lazy="extra"><key column="cid"></key><one-to-many class="org.example.entity.Orders"></one-to-many></set></class>
</hibernate-mapping>

 Orders 对象和 Orders.hbm.xml 映射文件

package org.example.entity;import lombok.Data;
import lombok.Getter;
import lombok.Setter;@Getter
@Setter
public class Orders {private Integer id;private String name;private Customer customer;@Overridepublic String toString() {return "Orders{" +"id=" + id +", name='" + name + '\'' +'}';}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping><class name="org.example.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><many-to-one name="customer" class="org.example.entity.Customer" column="cid" lazy="proxy"></many-to-one></class>
</hibernate-mapping>
package org.example;import org.example.entity.Customer;
import org.example.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test9 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession 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();//关闭sessionsession.close();}
}


package org.example;import org.example.entity.Customer;
import org.example.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;import java.util.HashSet;
import java.util.Set;public class Test9 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession 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);Set<Orders> orders = new HashSet<Orders>();orders.add(orders1);orders.add(orders2);customer.setOrders(orders);session.save(customer);session.save(orders1);session.save(orders2);session.beginTransaction().commit();//关闭sessionsession.close();}
}

因为 Customer 和 Orders 都在维护一对多关系,所以会重复设置主外键约束关系。

如何避免  这种情况?

1、在Java 代码中去掉一方维护关系代码。

2、通过配置来解决

<set name="orders" table="orders" lazy="extra" inverse="true"><key column="cid"></key><one-to-many class="org.example.entity.Orders"></one-to-many>
</set>

inverse属性是用来设置是否将维护权交给对方,默认是false,不交出维护权,双方都在维护,将它设置为true,表示 Customer放弃维护。

cascade:用来设置级联操作

因为映射文件主外键的关联,使其得先删除次表外键数据,再删除主表的主键数据,不然会报错

第一种方式:先循环删除外键数据,再删除要删除的主键数据

package org.example;import org.example.entity.Customer;
import org.example.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) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Customer customer = session.get(Customer.class,16);//用迭代器删除外键数据Iterator<Orders> iterator = customer.getOrders().iterator();while (iterator.hasNext()){session.delete(iterator.next());}//删除主键数据session.delete(customer);session.beginTransaction().commit();//关闭sessionsession.close();}
}

第二种方式:实体关系映射文件中设置cascade属性值为delete完成级联删除。

<set name="orders" table="orders" lazy="extra" inverse="true" cascade="delete"> <key column="cid"></key><one-to-many class="org.example.entity.Orders"></one-to-many>
</set>
package org.example;import org.example.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class Test10 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();Customer customer = session.get(Customer.class,15);session.delete(customer);session.beginTransaction().commit();//关闭sessionsession.close();}
}

Hibernate HQL

 HQL: Hibernate Query Language,是 Hibernate 框架提供的一种查询机制,它和 SQL 类似,不同的是 HQL 是面向对象的查询语句,让开发者能够以面向对象的思想来编写查询语句,对 Java 编程是一种好友好的方式。

HQL不能直接参与数据库的交互,中间层语言。

Java ---》HQL ---〉Hibernate ---》sQL ---〉DB

HQL 只能完成查询、修改、删除,新增是无法操作的。

1、查询对象

查询表中所有数据,自动完成对象的封装,返回List集合。

HQL进行查询,from 关键字后面不能写表名,必须写表对应的实体类名。

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;import java.util.List;public class Test8 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//查询people表的所有数据String hql = "from People";Query query = session.createQuery(hql);List<People> peoples = query.list();for (People p : peoples) {System.out.println(p);}session.beginTransaction().commit();//关闭sessionsession.close();}
}

2、分页查询

HQL分页查询可以通过调用query的方法来完成。

1、setFirstResult()        设置起始下标

2、setMaxResults()        设置截取长度

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;import java.util.List;public class Test11 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//分页查询String hql = "from People";Query query = session.createQuery(hql);query.setFirstResult(1);query.setMaxResults(3);List<People> list = query.list();for (People people : list){System.out.println(people);}//关闭sessionsession.close();}
}

查询结果,因下标0为起始,这里 这里  query.setFirstResult(1)就是表的第二行开始, query.setMaxResults(3)就是第二行开始往下三行都是分页查询数据。

 

3、where条件查询

HQL直接追加where关键字作为查询条件,与SQL没有区别。

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;public class Test11 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//where查询String hql = "from People where id = 2";Query query = session.createQuery(hql);People people = (People) query.list().get(0);System.out.println(people);session.close();}
}

query.list() 返回一个集合,此时集合中只有一个对象,通过下标 0 取出该对象。

注意:用 query.list().get() 取数据时,如果查询的数据集为空会报错。

解决方法:使用 query.uniqueResult() 方法则既可以查询数据,也不怕查询数据为空会报错,当数据集为空时会返回 null。

//where查询
String hql = "from People where id = 0";
Query query = session.createQuery(hql);
//使用 query.uniqueResult() 方法获取对象数据
People people = (People) query.uniqueResult();
System.out.println(people);

不会抛出异常。

4、模糊查询

 查询名称包含 “三” 的所有记录

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;import java.util.List;public class Test12 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//like模糊查询String hql = "from People where name like '%三%'";Query query = session.createQuery(hql);List<People> peoples = query.list();for (People people : peoples) {System.out.println(people);}session.close();}
}

 5、order by

按照id进行排序

升序

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;import java.util.List;public class Test13 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//按照id升序查询,不设置asc默认为升序//String hql = "from People order by id";String hql = "from People order by id asc ";Query query = session.createQuery(hql);List<People> peoples = query.list();for (People people : peoples) {System.out.println(people);}session.close();}
}

 

降序

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;import java.util.List;public class Test13 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//like模糊查询String hql = "from People order by id desc ";Query query = session.createQuery(hql);List<People> peoples = query.list();for (People people : peoples) {System.out.println(people);}session.close();}
}

 

asc 是升序排列,desc是降序排列

6、查询实体对象的属性

package org.example;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;public class Test14 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();//where查询String hql = "select name from People where id = 2";Query query = session.createQuery(hql);String name = (String) query.uniqueResult();System.out.println(name);session.close();}
}

 

7、占位符 

package org.example;import org.example.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;import java.util.List;public class Test15 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();String hql = "from People where name = :name";Query query = session.createQuery(hql);query.setString("name","张三");List<People> peoples = query.list();for (People people : peoples) {System.out.println(people);}session.close();}
}

8、级联查询

package org.example;import org.example.entity.Customer;
import org.example.entity.Orders;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;import java.util.List;public class Test16 {public static void main(String[] args) {//创建ConfigurationConfiguration configuration = new Configuration().configure();//获取SessionFactorySessionFactory sessionFactory = configuration.buildSessionFactory();//获取SessionSession session = sessionFactory.openSession();String hql1 = "from Customer where name = :name";Query query1 = session.createQuery(hql1);query1.setString("name","张三");Customer customer = (Customer) query1.list().get(0);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);}session.close();}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/332312.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Milvus Cloud 非结构化数据平台

从技术面来看,向量数据库底座自然而然向外延伸的产品包含: 1)向量提取,从非结构化数据中提取向量,这是向量数据库上游的工作,十分重要; 2)模型选择,选择正确的模型,能够更精准、更高质量地提取向量; 3)映射管理,即管理数据的本体和数据的语义层之间的映射,在…

【Linux杂货铺】进程通信

目录 &#x1f308; 前言&#x1f308; &#x1f4c1; 通信概念 &#x1f4c1; 通信发展阶段 &#x1f4c1; 通信方式 &#x1f4c1; 管道&#xff08;匿名管道&#xff09; &#x1f4c2; 接口 ​编辑&#x1f4c2; 使用fork来共享通道 &#x1f4c2; 管道读写规则 &…

01.并发编程简介

1 什么是并发编程 所谓并发编程是指在一台处理器上“同时”处理多个任务。并发是在同一实体上的多个事件。多个事件在同一时间间隔发生。 2 为什么我们要学习并发编程&#xff1f; 最直白的原因就是因为面试需要&#xff0c;大厂的 Java 岗的并发编程能力属于标配。 而在非大厂…

【Python特征工程系列】一文教你使用PCA进行特征分析与降维(案例+源码)

这是我的第287篇原创文章。 一、引言 主成分分析&#xff08;Principal Component Analysis, PCA&#xff09;是一种常用的降维技术&#xff0c;它通过线性变换将原始特征转换为一组线性不相关的新特征&#xff0c;称为主成分&#xff0c;以便更好地表达数据的方差。 在特征重要…

【数据结构】二叉树的认识与实现

目录 二叉树的概念&#xff1a; 二叉树的应用与实现&#xff1a; 二叉树实现接口&#xff1a; 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树 二叉树节点个数​编辑 二叉树叶子节点个数 二叉树第k层节点个数 二叉树查找值为x的节点​编辑 二叉树前序遍…

全网讲的最详细的Docker镜像分层存储原理

先说结论&#xff0c;容器镜像分层存储图示 欢迎关注 实验环境准备 当前实验docker版本24.0.7如下&#xff0c;当前docker版本使用overlay2机制存储镜像 Client: Docker Engine - CommunityVersion: 24.0.7API version: 1.43Go version: go1.20.10…

Redis第18讲——Redis和Redission实现延迟消息

即使不是做电商业务的同学&#xff0c;也一定知道订单超时关闭这种业务场景&#xff0c;这个场景大致就是用户下单后&#xff0c;如果在一定时间内未支付&#xff08;比如15分钟、半小时&#xff09;&#xff0c;那么系统就会把这笔订单给关闭掉。这个功能实现的方式有很多种&a…

《Ai学习笔记》-模型集成部署

后续大多数模型提升速度和精度&#xff1a; 提升速度&#xff1a; -知识蒸馏&#xff0c;以distillBert和tinyBert为代表 -神经网络优化技巧。prune来剪裁多余的网络节点&#xff0c;混合精度&#xff08;fp32和fp26混合来降低计算精度从从而实现速度的提升&#xff09; 提…

【Week-R1】RNN实现心脏病预测,基于tensorflow框架

文章目录 一、什么是RNN&#xff1f;二、准备环境和数据2.1 导入数据 三、构建模型四、训练和预测五、其他&#xff08;1&#xff09;sklearn模块导入报错&#xff1a;ModuleNotFoundError: No module named sklearn&#xff08;2&#xff09;优化器改为SGD&#xff0c;accurac…

SVM兵王问题

1.流程 前面六个就是棋子的位置&#xff0c;draw就是逼和&#xff0c;后面的数字six就代表&#xff0c;白棋最少用六步就能将死对方。然后呢&#xff0c;可以看一下最后一个有几种情况&#xff1a; 2.交叉测试 leave one out&#xff1a; 留一个样本作测试集&#xff0c;其余…

基于51单片机的超声波液位测量与控制系统

基于51单片机液位控制器 &#xff08;仿真&#xff0b;程序&#xff0b;原理图PCB&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.使用HC-SR04测量液位&#xff0c;LCD1602显示&#xff1b; 2.当水位高于设定上限的时候&#xff0c;对应声光报警报警&am…

【ai】pycharm安装langchain 相关module

pycharm module install 【Python学习 】一篇文章教你PyCharm如何快速安装module 【python】pycharm如何安装python的模块包版本 2024.1.2 RC2 找到当前的虚拟项目 找到解释器 我现在配置为专门为openai-start 准备的3.10 版本+ 号可以找到模块

leetcode-顺时针旋转矩阵-111

题目要求 思路 1.假设现在有一个矩阵 123 456 789 2.我们可以根据19这个对角线将数据进行交换&#xff0c;得到矩阵 147 258 369 3.然后将矩阵每一行的数据再翻转&#xff0c;得到矩阵 741 852 963 代码实现 class Solution { public:vector<vector<int> > rot…

设计模式深度解析:分布式与中心化,IT界两大巨头“华山论剑”

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL应用》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨IT界的两大巨头交锋✨ &#x1f44b; 在IT界的广阔天地中&#xff0c;有两座…

JavaFX安装与使用

前言 最近学习了javafx,开始时在配置环境和导包时遇到了一些麻烦,关于网上很多方法都尝试过了,现在问题都解决了,和大家分享一下我是怎么实现javafx的配置,希望大家可以通过这个方法实现自己的环境配置! &#x1f648;个人主页: 心.c &#x1f525;文章专题:javafx &#x1f49…

嵌入式实时操作系统笔记1:RTOS入门_理解简单的OS系统

今日开始学习嵌入式实时操作系统RTOS&#xff1a;UCOS-III实时操作系统 本次目标是入门RTOS&#xff0c;理解多任务系统...... 本文只是个人学习笔记&#xff0c;基本都是对网上资料的整合...... 目录 STM32裸机与RTOS区别&#xff1a; 裸机中断示例&#xff1a; RTOS对优先级…

9.Docker网络

文章目录 1、Docker网络简介2、常用基本命令3、网络模式对比举例3.1、bridge模式3.2、host模式3.3、none模式3.4、container模式3.5、自定义网络 1、Docker网络简介 作用&#xff1a; 容器间的互联和通信以及端口映射容器IP变动时候可以通过服务名直接进行网络通信而不受到影…

如何用ai打一场酣畅淋漓的数学建模比赛? 给考研加加分!

文章目录 数学建模比赛1. 数学建模是什么&#xff1f;2. 数学建模分工合作2.1 第一&#xff1a;组队和分工合作2.2 第二&#xff1a;充分的准备2.3 第三&#xff1a;比赛中写论文过程 3. 数学建模基本过程4. 2023全年数学建模竞赛时间轴5. 数学建模-资料大全6. 数学建模实战 数…

H3CNE-7-TCP和UDP协议

TCP和UDP协议 TCP&#xff1a;可靠传输&#xff0c;面向连接 -------- 速度慢&#xff0c;准确性高 UDP&#xff1a;不可靠传输&#xff0c;非面向连接 -------- 速度快&#xff0c;但准确性差 面向连接&#xff1a;如果某应用层协议的四层使用TCP端口&#xff0c;那么正式的…

2024GDCPC广东省赛记录

比赛流程体验&#xff0c;依托&#xff0c;开赛几分钟了&#xff0c;选手还卡在门外无法入场&#xff0c;也没给延时&#xff0c;说好的桌上会发三支笔&#xff0c;于是我们就没准备&#xff0c;要了三次笔&#xff0c;终于在一小时后拿到了&#x1f605; 比赛题目体验&#xf…