ORM将java类映射成表
1.如何使用?
- 导入相关依赖
- 创建Hibernate配置文件
- 创建实体类
- 创建实体类-关键映射文件
- 调用Hibernate API完成操作
2.具体使用 -实操
1)创建maven工程,pom.xml
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</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.10</version>
</dependency>
</dependencies>
2)在resources目录下创建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.username">root</property>
<property name="connection.password">123456</property>
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateTest?useUnicode=true&characterEncoding=UTF-8</property>
<!--c3p0-->
<property name="hibernate.c3p0.acquire_increment">10</property><!--不够了自己增加10条-->
<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">create</property>
</session-factory>
</hibernate-configuration>
3)创建实体类
@Data
//除了用@Data外,还可以用@Setter,@Getter,来生成对应的表
public class Customer {
private int id;
private String name;
private int age;
private Set<Order> orders;//一个客户对应多个订单,一对多关系
}
@Data
public class Order {
private int oid;
private String name;
private Customer customer;//多个订单对应一个用户
}
4)创建实体关系映射文件(关键)
customer.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.entry.Customer" table="customer">
<id name="id" type="java.lang.Integer"><!--主键映射-->
<column name="id"></column><!--主键的字段-->
<generator class="identity"></generator><!--identity主键自增-->
</id>
<!--name字段-->
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--一对多关联查询-->
<set name="orders" table="order">
<key column="oid"></key>
<one-to-many class="com.entry.Order"></one-to-many>
</set>
</class>
</hibernate-mapping>
- set标签来配置实体类中的集合属性order
- name实体类属性名
- table表名
- key外键
- one-to-many与集合泛型的实体类
order.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.entry.Order" table="Order">
<id name="oid" type="java.lang.Integer"><!--主键映射-->
<column name="id"></column><!--主键的字段-->
<generator class="identity"></generator><!--identity主键自增-->
</id>
<!--name字段-->
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--多对一关联查询 column="cid"为Order表的外键 -->
<many-to-one name="customer" class="com.entry.Customer" column="cid"></many-to-one>
</class>
</hibernate-mapping>
- many-to-one 配置实体类对应的对象属性
- name 属性名
- class 属性对应的类
- column 外键
5)实体关系映射文件注册到hibernate.cfg.xml文件中
<!--注册实体关系映射文件-->
<mapping resource="com/entry/Customer.xml"></mapping>
6)使用Hibernate API
public class test {
public static void main(String[] args) {
//创建Configuration
Configuration configuration=new Configuration().configure();
//获取SessionFactory
SessionFactory sessionFactory=configuration.buildSessionFactory();
//获取Session
Session session=sessionFactory.openSession();
//使用Hibernate操作数据库,都要开启事务,得到事务对象
Transaction transaction = session.getTransaction();
//开启事务
transaction.begin();
People p=new People();
p.setAge(12);
p.setPname("lqm");
//把对象添加到数据库中
session.save(p);
//提交事务
transaction.commit();
//关闭Session
session.close();
}
}
7)pom.xml中添加扫描xml的插件,不然扫描不到xml
<!--扫描dao层的xml文件-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
3.Hibernate级联操作-说明
1)一对多关系
一个客户对应多个订单,一个订单对应一个客户
2)多对多关系
学生选课:一门课程可以被多个学生选择,一个学生可以选择多门课程
数据库中是通过两个一对多关系来维护的,学生和课程都是主表,额外添加一张中间表作为从表,两张主表和中间表都是一对多关系。
比如:
4.Hibernate实现一对多-实操
Customer.java
@Data
//除了用@Data外,还可以用@Setter,@Getter,来生成对应的表
public class Customer {
private Integer id;
private String name;
private Set<Orders> orders;//一个客户对应多个订单,一对多关系
}
Orders.java
@Data
public class Orders {
private Integer id;
private String name;
private Customer customer;
}
xml中配置
customer.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.entry.Customer" table="customer">
<id name="id" type="java.lang.Integer"><!--主键映射-->
<column name="id"></column><!--主键的字段-->
<generator class="identity"></generator><!--identity主键自增-->
</id>
<!--name字段-->
<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="com.entry.Orders"></one-to-many>
</set>
</class>
</hibernate-mapping>
- set标签来配置实体类中的集合属性order
- name实体类属性名
- table表名
- key外键
- one-to-many与集合泛型的实体类
Order.xml中配置添加
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.entry.Orders" table="Orders">
<id name="id" type="java.lang.Integer"><!--主键映射-->
<column name="id"></column><!--主键的字段-->
<generator class="identity"></generator><!--identity主键自增-->
</id>
<!--name字段-->
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--多对一关联查询 column="cid"为Order表的外键 -->
<many-to-one name="customer" class="com.entry.Customer" column="cid"></many-to-one>
</class>
</hibernate-mapping>
- many-to-one 配置实体类对应的对象属性
- name 属性名
- class 属性对应的类
- column 外键
hibernate.cfg.xml中添加,扫描注解
<mapping resource="com/entry/Customer.xml"></mapping>
<mapping resource="com/entry/Order.xml"></mapping>
测试
public class test {
public static void main(String[] args) {
//创建Configuration
Configuration configuration=new Configuration().configure();
//获取SessionFactory
SessionFactory sessionFactory=configuration.buildSessionFactory();
//获取Session
Session session=sessionFactory.openSession();
//使用Hibernate操作数据库,都要开启事务,得到事务对象
Transaction transaction = session.getTransaction();
//开启事务
transaction.begin();
//用户
Customer customer=new Customer();
customer.setName("lqm");
//订单
Orders order1=new Orders();
order1.setName("订单1");
//建立关联关系
order1.setCustomer(customer);
//把对象添加到数据库中
session.save(customer);
session.save(order1);
//提交事务
transaction.commit();
//关闭Session
session.close();
}
}
其中
建立关联关系
order1.setCustomer(customer); 将customer存进order里面
orders中就能看到cid外键有customer的id了,这样一对多关联关系建立起来了
5.级联关系–多对多–实操
先创建中间表
Account.java
@Data
public class Account {
private Integer id;
private String name;
Set<Course> courses;
}
Account.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.entry.Account" table="account">
<id name="id" type="java.lang.Integer"><!--主键映射-->
<column name="id"></column><!--主键的字段-->
<generator class="identity"></generator><!--identity主键自增-->
</id>
<!--name字段-->
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<!--多对多关联查询 中间表-->
<set name="courses" table="account_course">
<key column="aid"></key> <!--aid对应account在中间表的外键-->
<many-to-many class="com.entry.Course" column="cid"></many-to-many><!--cid对应course在中间表的外键-->
</set>
</class>
</hibernate-mapping>
Course.java
@Data
public class Course {
private Integer id;
private String name;
Set<Account> accounts;
}
Course.xml
<!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.entry.Course" table="course">
<id name="id" type="java.lang.Integer"><!--主键映射-->
<column name="id"></column><!--主键的字段-->
<generator class="identity"></generator><!--identity主键自增-->
</id>
<!--name字段-->
<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="com.entry.Account" column="aid"></many-to-many>
</set>
</class>
</hibernate-mapping>
hibernate.cfg.xml中添加关联映射
<mapping resource="com/entry/Account.xml"></mapping>
<mapping resource="com/entry/Course.xml"></mapping>
测试
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();
//使用Hibernate操作数据库,都要开启事务,得到事务对象
Transaction transaction = session.getTransaction();
//开启事务
transaction.begin();
Course course=new Course();
course.setName("Java");
Account account=new Account();
account.setName("张三");
Set<Course> courses=new HashSet<>();
courses.add(course);
account.setCourses(courses);
session.save(course);
session.save(account);
//提交事务
transaction.commit();
//关闭Session
session.close();
}
}
你会发现后台打印了3条sql语句:
数据库中也有了相应的数据
6.Hibernate延迟加载
1.延迟加载可以看作是一种优化机制,根据具体的需求,自动选择要执行的sql数量
(set那里写lazy=true,或者可以设置lazy=extra,是比true更懒惰的一种加载方式,或者说是更加智能的加载方式)
比如:查询id为15的customer,如果还需要查询id=15的customer的orders的话,就需要先查询有没有id=15的customer,如果有就会 再去查id=15的customer的orders。这样就是两条sql语句。
说明:开启延时加载后,查询id=15的customer是一条sql,如果需要查询从表信息的话,就是主表和从表信息都查询,那就是两条sql。
关闭延时加载后,查询id=15的customer是两条sql,主表和从表都去查了一遍。如果关联到从表时,查询还是两条sql。
- no-proxy:当调用方法需要访问customer的成员变量时,发送sql语句查询Customer,否则不查询。
- proxy:无论调用方法是否需要访问customer的成员变量,都发送sql语句查询Customer。
7.Hibernate配置详解
Hibernate.cfg.xml中配置详解:
实体关系映射文件
比如:
比如:
除此之外还有下面的属性:
还有where属性,比如where id=6