hibernate
Hibernate是一款重量级的持久层框架,目前市面上的我很少见还有项目在开发时候使用他,之所以要学习这个,因为公司最近有一个系统升级的项目,之前的老系统用到了Hibernate。
同样还是老套路,学习一个新技术或者新知识,首先去他的官网看
【官网】:https://hibernate.org/orm/ 【官方教程】:https://hibernate.org/orm/documentation/getting-started/ 【github地址】:https://github.com/hibernate
目前hibernate已经更新到了6的版本,这里使用的5的版本
注意: Hibernate5.1;5.2官方推荐使用JDK1.8以及JDBC4
文章目录
一、generator主键策略
generator配置:代表hibernate主键生成策略
【我们可以将其分为三大类】:
- 由数据库维护
- identity:Mysql的
auto_increment
维护主键自增策略 - sequence:Oracle使用
sequence
序列维护主键自增策略 - native:本地策略,由hibernate自己根据数据库选择最优策略
- 由hibernate维护
- uuid:生成32位16进制的无效
字符串
【记住是一个字串】 - increment:生成递增的数值类型(每次先查当前的最大的id值+1)
- 由开发者维护
- asigned:必须要有程序员给定id的值,否则报错
二、对象关系映射:一对多映射
需求案例:客户 与 订单的需求关系:典型的一对多的关系
2.1 测试准备
这里我们需要在创建一张表t_order
CREATE TABLE `t_order` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`order_no` VARCHAR(20) NULL DEFAULT NULL COMMENT '订单编号' COLLATE 'utf8mb4_general_ci',
`product_name` VARCHAR(20) NULL DEFAULT NULL COMMENT '产品名称' COLLATE 'utf8mb4_general_ci',
`cust_id` INT(10) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `t_order_id_uindex` (`id`) USING BTREE,
INDEX `t_order_t_customer_c_id_fk` (`cust_id`) USING BTREE,
CONSTRAINT `t_order_t_customer_c_id_fk` FOREIGN KEY (`cust_id`) REFERENCES `hibernate_db`.`t_customer` (`c_id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=2;
2.2 创建实体
注意事项:
- 需要在Custom实体中先给一个
List<Order>
来关联多方的实体信息- order实体表也需要给一个Custom的JavaBean对其进行关联
【Order】
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
private String id; // 订单表主键
private String orderNo; // 订单编号
private String prodName; // 产品名称
private Integer custId; // 外键客户id
/*一个订单对一个客户,一个客户对多个订单*/
private Customer customer;
}
2.3 hbm.xml文件修改
【customer.hbm.xml】
在Custom.hbm.xml文件里,我们需要做的是将order进行关联用set标签
<class name="com.wei.domain.Customer" table="t_customer">
<id name="id" column="c_id">
<generator class="identity"></generator>
</id>
<property name="name" column="c_name"></property>
<property name="age" column="c_age"></property>
<property name="gender" column="c_gender"></property>
<property name="level" column="c_level"></property>
<!--一对多配置-->
<!--name设置本实体类(customer)关联的属性字段名-->
<set name="orders" >
<!--外键的字段名称-->
<key column="cust_id"></key>
<!--关联的实体对象的完整类路径-->
<one-to-many class="com.wei.domain.Order"/>
</set>
</class>
一表中的关联配置使用的标签是:
<one-to-many class="所关联的类的全类名"></on-to-mony>
【order.hbm.xml】
<class name="com.wei.domain.Order" table="t_order">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="orderNo" column="order_no"/>
<property name="prodName" column="product_name"/>
<!--多对一配置-->
<many-to-one name="customer" column="cust_id" class="com.wei.domain.Customer"></many-to-one>
</class>
多表中所关联的字段是用的标签是
<many-to-one name="关联的本实体类在的字段名" column="外键字段" class=“所引用的实体类的全类名”></many-to-one>
2.4 编写测试类
@Test
public void test1() throws HibernateException {
// 准备数据
/*
* 需求:一个客户两个订单
* */
Customer lisi = new Customer();
lisi.setName("里斯");
lisi.setGender("1");
lisi.setAge(32);
lisi.setLevel("至尊VIP,年卡8级");
Set<Order> orders = new HashSet<>();
// 订单1
Order order1 = new Order();
order1.setOrderNo("20220807111");
order1.setProdName("小米Ultr11");
order1.setCustomer(lisi);
// 订单2
Order order2 = new Order();
order2.setOrderNo("20220807134");
order2.setProdName("华为MateBook_Pro 512G+8G");
order2.setCustomer(lisi);
// 客户添加订单
orders.add(order1);
orders.add(order2);
lisi.setOrders(orders);
Session session = HibernateUtil.getConnection();
//4、开启事务
Transaction tx = session.beginTransaction();
//5、执行添加操作
session.save(lisi);
session.save(order1);
session.save(order2);
//6、提交事务
tx.commit();
//7、关闭资源
HibernateUtil.closeSession(session);
}
【订单表】
【客户表】
为了可以证实是否插入成功,我么可以再写一个方法来查询某一个客户的订单
/**
* 查询用户guan连查询其所的订单
*
* @throws HibernateException
*/
@Test
public void test2() throws HibernateException {
Session session = HibernateUtil.getConnection();
//4、开启事务
Transaction tx = session.beginTransaction();
//5、执行添加操作
Customer customer = session.get(Customer.class, 5);
System.out.println("用户名称:"+customer.getName());
Set<Order> orders = customer.getOrders();
for (Order order : orders) {
System.out.println("订单:"+order.getOrderNo());
}
//6、提交事务
tx.commit();
//7、关闭资源
HibernateUtil.closeSession(session);
}
三、casecode和inverse配置
3.1 CaseCade级联操作
级联操作,就是操作一个对象的时候,相同时操作他的关联对象。
- 级联保存
<set name="orders" cascade="save-update">
<!--外键的字段名称-->
<key column="cust_id"></key>
<one-to-many class="com.wei.domain.Order"/>
</set>
【测试】
@Test
public void test3() throws HibernateException {
// 准备数据
Customer lisi = new Customer();
lisi.setName("马云云");
lisi.setGender("1");
lisi.setAge(34);
lisi.setLevel("至尊VIP,年卡n级");
Set<Order> orders = new HashSet<>();
// 订单1
Order order1 = new Order();
order1.setOrderNo("20220808123");
order1.setProdName("阿里巴巴");
order1.setCustomer(lisi);
// 订单2
Order order2 = new Order();
order2.setOrderNo("20220808141");
order2.setProdName("华强北 只能IPHONE watch");
order2.setCustomer(lisi);
// 客户添加订单
orders.add(order1);
orders.add(order2);
lisi.setOrders(orders);
Session session = HibernateUtil.getConnection();
//4、开启事务
Transaction tx = session.beginTransaction();
//5、执行添加操作
session.save(lisi); // 保存客户
// 级联保存订单数据,所以配置在客户的映射文件中
//6、提交事务
tx.commit();
//7、关闭资源
HibernateUtil.closeSession(session);
}
- 级联删除
<set name="orders" cascade="save-update,delete" >
<!--外键的字段名称-->
<key column="cust_id"></key>
<one-to-many class="com.wei.domain.Order"/>
</set>
【测试】
@Test
public void test4() throws HibernateException {
Session session = HibernateUtil.getConnection();
//4、开启事务
Transaction tx = session.beginTransaction();
//5、执行添加操作
Customer cus = session.get(Customer.class, 6);// 级联删除
//6、提交事务
session.delete(cus);
tx.commit();
//7、关闭资源
HibernateUtil.closeSession(session);
}
如果没有级联删除,则会把外键的值置为空。
级联删除则会在删除一个对象的同时将其关联的的对象也删除。
【实现级联操作的注意事项】:
标签:session,hibernate,框架,lisi,--,private,级联,Hibernate,id From: https://blog.51cto.com/u_14957231/5725634