1.什么是hibernate
- Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库
2.使用hibernate
-
首先创建一个maven的web项目
-
在maven项目里面加入hibernate和你使用的数据库驱动(这里我用的是一个mysql)的依赖
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.10.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.44</version> </dependency>
3.hibernate的工作流程
如果只是单独的说一个Hibernate的流程主要分为以下八个步骤:
1.读取并解析配置文件(Hibernate_config.xml) 创建Configuration类的实例,它的构造方法将配置文件读入到内存中,一个Configuration实例代表Hibernate所有Java类到数据库映射的集合。
2.读取并解析映射信息,创建SessionFactory实例把Configuration对象中的所有配置信息拷贝到SessionFactory缓存中。SessionFactory的实例代表一个数据库存储源,创建后不再与Configuration对象关联。
3.调用SessionFactory创建Session的方DAA法,打开Sesssion
Session session = sessionFactory.openSession();
但在SSH框架中打开Session的过程交给了org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
4.创建事务Transation
5.持久化操作, 通过Session接口提供的各种方法来操纵数据库访问
*6.*提交事务
7.关闭Session
8.关闭SesstionFactory
而在SSH框架中,Hibernate很多步骤都交给了Spring容器管理比如加载配置文件、打开和关闭Session、事务管理*….*等等
4.hibernate的配置
- 创建一个hibernate.cfg.xml
<session-factory>
<property name="connection.username">root</property> <!--配置与数据连接的用户名 -->
<property name="connection.password">123456</property> <!--密码 -->
<property name="connection.url">jdbc:mysql://localhost:3306/bookshop?useUnicode=true&characterEncoding=utf-8&useSSL=false</property> <!-- url -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!--驱动所在的位置 -->
<!-- 方言 每种类型的数据库的方言不同,我这里使用的是一个mysql -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property><!-- 是否可以显示sql语句 (true 可以显示 false显示)-->
<property name="format_sql">true</property><!--让显示的sql更加的工整 -->
<!-- 映射文件 (hibernate.cfg.xml是hibernate的默认配置文件,一般会加载这个文件。在这个文件里里面的所有的映射放到Configuration,再通过这个Configuration创建SessionFactory。在执行对应的增删改查的方法。所以需要把表与数据的映射放到hibernate.cfg.xml中)-->
<mapping resource="mapping/User.hbm.xml"/>
</session-factory>
-
创建数据库表和实体bean和数据的对应
创建数据库表(t_user)
create table t_user ( id int not null primary key, -- ID:主键,注:没有设置为自动增长 user_name varchar(50) not null, -- 用户名 user_pwd varchar(10) not null, -- 密码 real_name varchar(50), -- 真实姓名 sex char(2), -- 性别 birthday datetime, -- 出生日期 create_datetime timestamp NULL default CURRENT_TIMESTAMP, -- 创建日期时间,默认为系统当前时间 remark varchar(1024) -- 备注 ); insert into t_user(id,user_name,user_pwd,real_name,sex,birthday,create_datetime,remark) values(1,'zs','123','张三','男',20001010,null,'abcd'); insert into t_user(id,user_name,user_pwd,real_name,sex,birthday,remark) values(2,'ls','123','李四','男',20001110,'xyz');
创建一个实体bean
public class User implements java.io.Serializable { private Integer id; private String userName; private String userPwd; private String realName; private String sex; private Date birthday; private Date createDatetime; private String remark; //... 生成getter,setter }
配置实体bean的和数据库表(t_user)的关系映射
<?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.zking.hbdemo.entity.User" table="t_user"> <id name="id" type="java.lang.Integer"> <column name="id"/> <generator class="increment"/> </id> <property name="userName" type="java.lang.String" column="user_name"/> <property name="userPwd" type="java.lang.String" column="user_pwd"/> <property name="realName" type="java.lang.String" column="real_name"/> <property name="sex" type="java.lang.String" column="sex"/> <property name="birthday" type="java.util.Date" column="birthday"/> <property name="createDatetime" type="java.util.Date" column="create_datetime"/> <property name="remark" type="java.lang.String" column="remark"/> </class> </hibernate-mapping>
说明:
native : 由Hibernate根据底层数据库自行判断采用identity、sequence其中一种作为主键生成方式。
identity : 采用数据库提供的主键生成机制
sequence : 采用数据库提供的sequence 机制生成主键。如Oralce 中的Sequence
increment: 主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。 在多线程情况下可能出现主键重复的问题(一般不在生成环境中使用)
5.操作的具体实例
public class HbDemo {
//增加
@Test
public void testSave() {
//1. 读取配置
Configuration conf = new Configuration();
conf.configure("hibernate.cfg.xml");
//2. 通过Configuration对象创建SessionFactory
SessionFactory sFactory= conf.buildSessionFactory();
//3. 通过SessionFactory获取Session
Session session = sFactory.openSession();
//4. 开启事务
Transaction transcation = session.beginTransaction();
//5. 操作数据库 ....
User user = new User();
user.setUserName("aq");
user.setUserPwd("123456");
user.setRealName("测试");
user.setRemark("测试记录");
user.setBirthday(new Date(System.currentTimeMillis()));
user.setCreateDatetime(new Date(System.currentTimeMillis()));
//通过session执行保存
Serializable row = session.save(user);
System.out.println("影响行数 = " + row);
//6. 提交事务
transcation.commit();
//7. 关闭Session
session.close();
}
}
6.对象的三种状态
在hibernate中对象中又三种状态:临时状态,持久状态,游离状态。三三种状态的转换图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Has1pivv-1596690948013)(新建文本文档.assets/image-20200802134708043.png)]
session.flush() 清空一级缓存
游离状态的对象发生状态也不会被更新到数据中,(快照消失,没有判断的依据)
session.evict(u)移除某一个
7. 加载策略
-
延迟加载, load()方法根据配置文件使用延时加载,默认为延时加载。
-
立即加载,session.get()忽略加载策略,使用立即加载。
-
区别
-
load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常;get方法检索不到的话会返回null;
-
load方法的执行则比较复杂首先查找session的persistent Context(一级缓存)中是否有缓存,如果有则直接返回,如果没有则去查找二级缓存,如果有则返回,如果没有则判断是否是lazy,若不是lazy,直接访问数据库检索,查到记录返回(并且同时在二级缓存中存放查到的数据方便下次使用,若再下次使用时在二级缓存命中,就是查到数据,则有可能将数据放到
一级缓存中。),查不到抛出异常。 若是lazy,则返回代理对象,而不到数据库中查找,除非使用此对象时,才到数据库中查找。
get方法先到一级缓存,然后二级,最后db查找。
-
延迟加载实例(hibernate3默认lazy默认是true)
\\写一个测试的dao层
public class UserDao {
public User load(int id) {
Session session = SessionFactoryUtil.OpenSession();
User user = session.load(User.class, id);
SessionFactoryUtil.closeSession();
return user;
}
}
\\编写测试
public class UserDaoTest {
private UserDao userDao = new UserDao();
@Test
public void testLoad() {
User user = userDao.load(4);
//id为主键,可正常输出
System.out.println(user.getId());
/*
* 此处将包异常,
* 原因:load为延时加载,此时只会预先加载主键值,userDao.load()方法返回,
* session将关闭,在需要使用非主键值时,根据延时加载策略,此时需要到数据库中
* 加载非主键值(延时加载,即使用时再加载),此时的session已经关闭。所以会报
* 出异常。
* load方法返回的实际上是一个代理对象,其中只用主键值(对象标识,oid)有值,其他的非
* 主键值是没有值的,在第一次使用非oid属性时在从数据库中去加载非oid属性的值。
* 作为测试,可以在load()方法返回前任意读取一个非oid属性,此处将不再抛出异常。
*/
System.out.println(user.getRealName());
}
}
8.关联
关联分析又称关联挖掘,就是在交易数据、关系数据或其他信息载体中,查找存在于项目集合或对象集合之间的频繁模式、关联、相关性或因果结构。在hibernate存在着一对一和多对多,一对多的关联。
从对象的角度看,关联就是对象之间存在引用的关系
public class B {
...
}
public class A {
private B b = new B();
...
}
从数据库角度看,关联主要体现在外键上 ,比如一个表外键引用另一张的主键。
9.实例(一对多)
-
创建数据库的实例
-- 订单表(主表) create table t_order ( order_id int primary key auto_increment, order_no varchar(50) not null ); -- 订单项表(从表) create table t_order_item ( order_item_id int primary key auto_increment, product_id int not null, quantity int not null, oid int not null, foreign key(oid) references t_order(order_id) ); -- 一对多双向自关联 -- 菜单表 -- t_sys_tree_node -- t:表 -- sys:模块名缩写(system) -- tree_noe:表名 create table t_sys_tree_node ( tree_node_id int primary key auto_increment, -- ID tree_node_name varchar(50) not null, -- 名字 tree_node_type int not null check(tree_node_type = 1 or tree_node_type = 2), -- 节点类型:1 枝节点 2 叶节点 position bigint, -- 位置 parent_node_id int, -- 父节点ID url varchar(1024), -- URL foreign key(parent_node_id) references t_sys_tree_node(tree_node_id) ); -- drop table t_sys_tree_node -- select * from t_sys_tree_node select * from t_sys_tree_node; truncate table t_sys_tree_node; insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(1,'系统管理',1, 1,null,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(2,'市场管理',1, 2,null,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(3,'字典管理',2, 3,1,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(4,'用户管理',2, 4,1,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(5,'角色管理',2, 5,1,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(6,'权限管理',1, 6,1,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(7,'进货管理',2, 7,2,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(8,'销售管理',2, 8,2,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(9,'库存管理',2, 9,2,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(10,'用户分配角色',2, 10,6,null); insert into t_sys_tree_node(tree_node_id, tree_node_name, tree_node_type, position, parent_node_id, url) values(11,'角色授予用户',2, 11,6,null);
-
创建对象关系实例
package com.zking.hibernatedemo2.entity; // Generated 2020-8-2 17:12:03 by Hibernate Tools 4.3.5.Final import java.util.HashSet; import java.util.Set; /** * TOrder generated by hbm2java */ public class TOrder implements java.io.Serializable { private Integer orderId; private String orderNo; private Set<TOrderItem> TOrderItems = new HashSet<TOrderItem>(); private int initOrderitem=0; public int getInitOrderitem() { return initOrderitem; } public void setInitOrderitem(int initOrderitem) { this.initOrderitem = initOrderitem; } public TOrder() { } public TOrder(String orderNo) { this.orderNo = orderNo; } public TOrder(String orderNo, Set TOrderItems) { this.orderNo = orderNo; this.TOrderItems = TOrderItems; } public Integer getOrderId() { return this.orderId; } public void setOrderId(Integer orderId) { this.orderId = orderId; } public String getOrderNo() { return this.orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public Set getTOrderItems() { return this.TOrderItems; } public void setTOrderItems(Set TOrderItems) { this.TOrderItems = TOrderItems; } @Override public String toString() { return "TOrder [orderId=" + orderId + ", orderNo=" + orderNo + ", TOrderItems=" + TOrderItems + "]"; } }
package com.zking.hibernatedemo2.entity; // Generated 2020-8-2 17:12:03 by Hibernate Tools 4.3.5.Final /** * TOrderItem generated by hbm2java */ public class TOrderItem implements java.io.Serializable { private Integer orderItemId; private Integer productId; private Integer quantity; private Integer oid; //多对一 private TOrder TOrder; public TOrderItem() { } public TOrderItem( Integer productId, Integer quantity, TOrder t) { super(); this.productId = productId; this.quantity = quantity; this.TOrder = t; } public int getOid() { return oid; } public void setOid(int oid) { this.oid = oid; } public Integer getOrderItemId() { return this.orderItemId; } public void setOrderItemId(Integer orderItemId) { this.orderItemId = orderItemId; } public TOrder getTOrder() { return this.TOrder; } public void setTOrder(TOrder TOrder) { this.TOrder = TOrder; } public int getProductId() { return this.productId; } public void setProductId(int productId) { this.productId = productId; } public int getQuantity() { return this.quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } @Override public String toString() { return "TOrderItem [orderItemId=" + orderItemId + ", productId=" + productId + ", quantity=" + quantity + ",oid="+oid+"]"; } }
-
配置文件实例
<?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"> <!-- Generated 2020-8-2 17:12:03 by Hibernate Tools 4.3.5.Final --> <hibernate-mapping> <class name="com.zking.hibernatedemo2.entity.TOrder" table="t_order" > <id name="orderId" type="java.lang.Integer"> <column name="order_id" /> <generator class="increment" /> </id> <property name="orderNo" type="string"> <column name="order_no" /> </property> <!--一对多 --> <!--inverse 表示主控方的意思默认是false。指定之后就是该类就是主控方 --> <set name="TOrderItems" table="t_order_item" inverse="false" cascade="save-update" ><!-- cascade ="save-update" 表示保存和更新会级联处理--> <key> <column name="oid"/> </key> <one-to-many class="com.zking.hibernatedemo2.entity.TOrderItem" /> </set> </class> </hibernate-mapping> <!-- cascade属性的配置项说明如下: none: 保存,更新或删除当前对象时,忽略其它关联的对象 save-update:保存、更新时级联保存所有的临时对象,并且级联更新关联的游离对象 delete:通过session的delete方法删除当前对象,级联删除关联的对象 all:等于save-update操作+delete操作 inverse: 在一对多关系的配置中另外还配置了一个inverse属性,该属性的作用是设置主控方。默认值为false,true表示将对方设置为主控方(一对多双向关联中一般将多方设置为主控方,这样可以减少SQL语句的数量,减少多余的操作)。 lazy: 默认值为true,true延迟加载,false立即加载(一般设置为true,不使用立即加载,因为影响查询性能)-->
<?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"> <!-- Generated 2020-8-2 17:12:03 by Hibernate Tools 4.3.5.Final --> <hibernate-mapping> <class name="com.zking.hibernatedemo2.entity.TOrderItem" table="t_order_item"> <id name="orderItemId" type="java.lang.Integer"> <column name="order_item_id" /> <generator class="increment" /> </id> <property name="productId" type="java.lang.Integer"> <column name="product_id" /> </property> <property name="quantity" type="java.lang.Integer"> <column name="quantity" /> </property> <!--oid的属性值去order中的order_id,最简单的方式将该配置删掉,或者是配置 insert="false" --> <!-- <property name="oid" type="java.lang.Integer" column="oid" insert="false" update="false"/> --> <many-to-one name="TOrder" class="com.zking.hibernatedemo2.entity.TOrder" > <column name="oid"/> </many-to-one> </class> </hibernate-mapping>
测试
package com.zking.hibernatedemo2.dao; import javax.persistence.criteria.Order; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import com.zking.hibernatedemo2.entity.TOrder; import com.zking.hibernatedemo2.utils.GetSession; public class OrderDao { public int add(TOrder order) { Session session = GetSession.getSession(); Transaction transaction = session.beginTransaction(); int save =(int) session.save(order); transaction.commit(); return save; } public TOrder select(TOrder o) { Session session = GetSession.getSession(); TOrder order = session.load(TOrder.class,o.getOrderId()); //强制初始化一个代理 if(o.getInitOrderitem()== 1) { Hibernate.initialize(order.getTOrderItems()); } GetSession.closeSession(); return order; } public void del() { } }
package hibernatedemo2.test; import java.util.HashSet; import java.util.Set; import javax.persistence.criteria.Order; import org.apache.jasper.tagplugins.jstl.core.ForEach; import org.junit.Test; import com.zking.hibernatedemo2.dao.OrderDao; import com.zking.hibernatedemo2.entity.TOrder; import com.zking.hibernatedemo2.entity.TOrderItem; public class demo01 { //增加 @Test public void test1() { TOrder order=new TOrder(); OrderDao dao=new OrderDao(); Set<TOrderItem> set=new HashSet<>(); for(int i=1;i<=10;i++) { TOrderItem item=new TOrderItem(i,i,order); set.add(item); } order.setOrderNo("DD008"); order.setTOrderItems(set); int add = dao.add(order); System.out.println(add); } //查看 @Test public void test2() { TOrder order=new TOrder(); OrderDao dao=new OrderDao(); order.setOrderId(1); order.setInitOrderitem(1); TOrder order2 = dao.select(order); order2.getTOrderItems().forEach((a)->System.out.println(a)); System.out.println( order2.getOrderId()); System.out.println( order2.getOrderNo()); } //删除(只能删除没有联系的值,如果删除又联系的值会报错) @Test public void test3() { TOrder order=new TOrder(); OrderDao dao=new OrderDao(); order.setOrderId(4); dao.del(order); } }
-
10.实例(自关联)
-
创建对象关系实例
package com.zking.hibernatedemo2.entity; // Generated 2020-8-2 17:12:03 by Hibernate Tools 4.3.5.Final import java.util.ArrayList; /*import java.util.HashSet;*/ import java.util.List; /*import java.util.Set;*/ import java.io.Serializable; /** * TSysTreeNode generated by hbm2java */ public class TSysTreeNode implements Serializable { private Integer treeNodeId; private String treeNodeName; private int treeNodeType; private Long position; private String url; /*private Set<TSysTreeNode> TSysTreeNodes = new HashSet();*/ private List<TSysTreeNode> childNodes = new ArrayList<TSysTreeNode>(); private TSysTreeNode TSysTreeNode; private int initChildNodes=0; public TSysTreeNode() { } /*public TSysTreeNode(String treeNodeName, int treeNodeType) { this.treeNodeName = treeNodeName; this.treeNodeType = treeNodeType; }*/ public TSysTreeNode(String treeNodeName, Long position) { this.treeNodeName=treeNodeName; this.treeNodeType=2; this.position=position; } public int getInitChildNodes() { return initChildNodes; } public void setInitChildNodes(int initChildNodes) { this.initChildNodes = initChildNodes; } public Integer getTreeNodeId() { return this.treeNodeId; } public void setTreeNodeId(Integer treeNodeId) { this.treeNodeId = treeNodeId; } public TSysTreeNode getTSysTreeNode() { return this.TSysTreeNode; } public void setTSysTreeNode(TSysTreeNode TSysTreeNode) { this.TSysTreeNode = TSysTreeNode; } public String getTreeNodeName() { return this.treeNodeName; } public void setTreeNodeName(String treeNodeName) { this.treeNodeName = treeNodeName; } public int getTreeNodeType() { return this.treeNodeType; } public void setTreeNodeType(int treeNodeType) { this.treeNodeType = treeNodeType; } public Long getPosition() { return this.position; } public void setPosition(Long position) { this.position = position; } public String getUrl() { return this.url; } public void setUrl(String url) { this.url = url; } /* public Set getTSysTreeNodes() { return this.TSysTreeNodes; } public void setTSysTreeNodes(Set TSysTreeNodes) { this.TSysTreeNodes = TSysTreeNodes; }*/ public List<TSysTreeNode> getChildNodes() { return childNodes; } public void setChildNodes(List<TSysTreeNode> childNodes) { this.childNodes = childNodes; } @Override public String toString() { return "TSysTreeNode [treeNodeId=" + treeNodeId + ", treeNodeName=" + treeNodeName + ", treeNodeType=" + treeNodeType + ", position=" + position + ", url=" + url + "]"; } }
-
创建数据库关系映射配置文件
<?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"> <!-- Generated 2020-8-2 17:12:03 by Hibernate Tools 4.3.5.Final --> <hibernate-mapping> <class name="com.zking.hibernatedemo2.entity.TSysTreeNode" table="t_sys_tree_node" catalog="westos" optimistic-lock="version"> <id name="treeNodeId" type="java.lang.Integer"> <column name="tree_node_id" /> <generator class="increment" /> </id> <property name="treeNodeName" type="string"> <column name="tree_node_name" length="50" not-null="true" /> </property> <property name="treeNodeType" type="int"> <column name="tree_node_type" not-null="true" /> </property> <property name="position" type="java.lang.Long"> <column name="position" /> </property> <property name="url" type="string"> <column name="url" length="1024" /> </property> <many-to-one name="TSysTreeNode" class="com.zking.hibernatedemo2.entity.TSysTreeNode"> <column name="parent_node_id" /> </many-to-one> <!--set方式 --> <!-- <set name="TSysTreeNodes" table="t_sys_tree_node" inverse="false" cascade="save-update"> <key> <column name="parent_node_id" /> </key> <one-to-many class="com.zking.hibernatedemo2.entity.TSysTreeNode" /> </set> --> <!-- list 按指定的order-by条件进行排序,注意:条件中是列名而不是属性名--> <bag name="childNodes" cascade="save-update" inverse="false" order-by="position asc"> <key column="parent_node_id"/> <one-to-many class="com.zking.hibernatedemo2.entity.TSysTreeNode"/> </bag> </class> </hibernate-mapping>
-
创建测试用到dao
package com.zking.hibernatedemo2.dao; import java.io.Serializable; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import com.zking.hibernatedemo2.entity.TSysTreeNode; import com.zking.hibernatedemo2.utils.GetSession; public class TreeNodeDao { /* public TSysTreeNode get(TSysTreeNode t) { Session session = GetSession.getSession(); return null; } */ public int add(TSysTreeNode t) { Session session = GetSession.getSession(); Transaction transaction = session.beginTransaction(); int save =(int) session.save(t); transaction.commit(); session.close(); return save; } public TSysTreeNode select(TSysTreeNode t) { Session session = GetSession.getSession(); TSysTreeNode treeNode=session.load(TSysTreeNode.class,t.getTreeNodeId()); //强制初始化一个代理 if(1==t.getInitChildNodes()) { Hibernate.initialize(treeNode.getChildNodes()); } GetSession.closeSession(); return treeNode; } }
-
测试
package hibernatedemo2.test; import java.util.ArrayList; import java.util.List; import org.apache.jasper.tagplugins.jstl.core.ForEach; import org.junit.Test; import com.zking.hibernatedemo2.dao.TreeNodeDao; import com.zking.hibernatedemo2.entity.TSysTreeNode; public class demo02 { private TreeNodeDao dao=new TreeNodeDao(); //增加 @Test public void add() { TSysTreeNode father=new TSysTreeNode(); List<TSysTreeNode> list=new ArrayList<>(); for(int i=13;i<=16;i++) { TSysTreeNode t=new TSysTreeNode("书籍删除"+i,(long)i); t.setTSysTreeNode(father); list.add(t); } father.setTreeNodeType(1); father.setPosition((long)12); father.setTreeNodeName("书记管理"); father.setChildNodes(list); dao.add(father); } //查看 @Test public void select() { TSysTreeNode tree=new TSysTreeNode(); tree.setTreeNodeId(1); tree.setInitChildNodes(1); TSysTreeNode node = dao.select(tree); node.getChildNodes().forEach((a)->System.out.println(a)); } }
11.实例(多对多)
- 创建数据库的数据
-- 书本类别表
create table t_category
(
category_id int primary key auto_increment,
category_name varchar(50) not null
);
-- 书本表
create table t_book
(
book_id int primary key auto_increment,
book_name varchar(50) not null,
price float not null
);
-- 桥接表
-- 定义三个列,其实只要两个列
-- 一个类别对应多本书,一本书对应多个类别
create table t_book_category
(
bcid int primary key auto_increment,
bid int not null,
cid int not null,
foreign key(bid) references t_book(book_id),
foreign key(cid) references t_category(category_id)
);
-
创建实体多对多关系
-
Category.java
public class Category implements Serializable { private Integer categoryId; private String categoryName; //一种类型可以对应多本书 private Set<Book> books = new HashSet<>(); public Set<Book> getBooks() { return books; } public void setBooks(Set<Book> books) { this.books = books; } public Integer getCategoryId() { return categoryId; } public void setCategoryId(Integer categoryId) { this.categoryId = categoryId; } public String getCategoryName() { return categoryName; } public void setCategoryName(String categoryName) { this.categoryName = categoryName; } @Override public String toString() { return "Category [categoryhljs-string" style="color: #d69d85; line-height: 160%; box-sizing: content-box;">", categoryName=" + categoryName + "]"; } }
Book.java
public class Book implements Serializable { private Integer bookId; private String bookName; private Float price; //一本书可以对应多种类型 private Set<Category> categorys = new HashSet<>(); public Set<Category> getCategorys() { return categorys; } public void setCategorys(Set<Category> categorys) { this.categorys = categorys; } public Integer getBookId() { return bookId; } public void setBookId(Integer bookId) { this.bookId = bookId; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } @Override public String toString() { return "Book [bookhljs-string" style="color: #d69d85; line-height: 160%; box-sizing: content-box;">", bookName=" + bookName + ", price=" + price + "]"; } }
-
-
配置文件
<?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.zking.hbdemo.entity.Book" table="t_book"> <!-- OID对象标识列 主键列 --> <id name="bookId" type="java.lang.Integer" column="book_id"> <generator class="native"></generator> </id> <property name="bookName" type="string" column="book_name" /> <property name="price" type="java.lang.Float" column="price" /> <!-- select * from t_book t1 inner join t_book_category_hb4 t2 on t1.book_id = t2.bid inner join t_category_hb4 t3 on t2.cid = t3.category_id --> <set name="categorys" cascade="save-update" inverse="false" table="t_book_category"> <key column="bid"/> <many-to-many class="com.zking.hbdemo.entity.Category" column="cid"/> </set> </class> </hibernate-mapping> <?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.zking.hbdemo.entity.Category" table="t_category"> <!-- OID对象标识列 主键列 --> <id name="categoryId" type="java.lang.Integer" column="category_id"> <generator class="native"/> </id> <property name="categoryName" type="string" column="category_name"/> <!-- select * from t_category_hb4 t1 inner join t_book_category_hb4 t2 on t1.category_id = t2.cid inner join t_book_hb4 t3 on t2.bid = t3.book_id --> <set name="books" cascade="save-update" inverse="true" table="t_book_category"> <key column="cid"/> <many-to-many class="com.zking.hbdemo.entity.Book" column="bid"/> </set> </class> </hibernate-mapping> 再把这两个配置到hibernate核心配置文件中去
-
编写dao
package com.zking.hibernatedemo2.dao; import java.io.Serializable; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import com.zking.hibernatedemo2.entity.Book; import com.zking.hibernatedemo2.entity.Category; import com.zking.hibernatedemo2.utils.GetSession; public class BookDao { public Book get(Book b) { Session session = GetSession.getSession(); Book get = session.load(Book.class,b.getBookId()); if(b.getInin()==1) { Hibernate.initialize(get.getCategorys()); Hibernate.initialize(get.getBookId()); } GetSession.closeSession(); return get; } public Category get(Category c) { Session session = GetSession.getSession(); Transaction transaction = session.beginTransaction(); Category get = session.get(Category.class,c.getCategoryId()); if(c.getInin()==1) { Hibernate.initialize(get.getBooks()); Hibernate.initialize(get.getCategoryId()); } transaction.commit(); GetSession.closeSession(); return get; } public int add(Book book) { Session session = GetSession.getSession(); Transaction transaction = session.beginTransaction(); int save =(int) session.save(book); transaction.commit(); GetSession.closeSession(); return save; } public int add(Category category) { Session session = GetSession.getSession(); Transaction transaction = session.beginTransaction(); int save =(int) session.save(category); transaction.commit(); GetSession.closeSession(); return save; } /* public void delBook(Book book) { Session session =GetSession.getSession(); Transaction t = session.beginTransaction(); Book b = session.get(Book.class, book.getBookId()); if(null!=b) { session.delete(b); } t.commit(); GetSession.closeSession(); } */ public void delCategory(Category category) { Session session =GetSession.getSession(); Transaction t = session.beginTransaction(); Category c = session.get(Category.class, category.getCategoryId()); if(null!=c) { for(Book book: c.getBooks()) { //错误,需要解除的是关联关系,书为主控方 //通过book获取书本对应的categorys,再删除对应的category //c.getBooks().remove(book); book.getCategorys().remove(c); } session.delete(c); } t.commit(); GetSession.closeSession(); } /*//必須是主控方category才能级联操作。 public void delCategory(Category category) { Session session =GetSession.getSession(); Transaction t = session.beginTransaction(); Category c = session.get(Category.class, category.getCategoryId()); if(c != null) { //删除被控方需要先解除关联关系 for(Book book: c.getBooks()) { //错误,需要解除的是关联关系,书为主控方 //通过book获取书本对应的categorys,再删除对应的category //c.getBooks().remove(book); book.getCategorys().remove(c); } session.delete(c); } t.commit(); GetSession.closeSession(); }*/ }
-
测试
package hibernatedemo2.test; import java.util.Objects; import org.junit.Test; import com.zking.hibernatedemo2.dao.BookDao; import com.zking.hibernatedemo2.entity.Book; import com.zking.hibernatedemo2.entity.Category; public class demo3 { //add /* @Test public void add() { BookDao bookDao=new BookDao(); Book book=new Book(); book.setBookName("圣墟"); book.setPrice(100f); Category category=new Category(); category.setCategoryName("武侠"); category.getBooks().add(book); Category category1=new Category(); category1.setCategoryName("古典"); category1.getBooks().add(book); book.getCategorys().add(category); book.getCategorys().add(category1); int add = bookDao.add(book); System.out.println(add); }*/ /* @Test public void add() { BookDao bookDao=new BookDao(); Book book=new Book(); book.setBookName("西游记"); book.setPrice(100f); Book book1=new Book(); book1.setBookName("红楼梦"); book1.setPrice(100f); Book book2=new Book(); book2.setBookName("三国演义"); book2.setPrice(100f); Book book3=new Book(); book3.setBookName("水浒传"); book3.setPrice(100f); Category category=new Category(); category.setCategoryName("四大名著"); category.getBooks().add(book); category.getBooks().add(book1); category.getBooks().add(book2); category.getBooks().add(book3); book.getCategorys().add(category); book1.getCategorys().add(category); book2.getCategorys().add(category); book3.getCategorys().add(category); int add = bookDao.add(category); System.out.println(add); }*/ //删除 /* @Test public void del() { Book book=new Book(); book.setBookId(18); BookDao dao=new BookDao(); dao.delBook(book); } */ //删除 /* @Test public void del() { Category c=new Category(); c.setCategoryId(5); BookDao dao=new BookDao(); dao.delCategory(c); }*/ //查看 @Test public void select() { Category c=new Category(); c.setCategoryId(17); c.setInin(1); BookDao dao=new BookDao(); Category category = dao.get(c); System.out.println(category); if(Objects.isNull(category.getBooks())) { System.out.println(123123); } category.getBooks().forEach((a)->System.out.println(a)); } /* @Test public void select() { Book c=new Book(); c.setBookId(23); c.setInin(1); BookDao dao=new BookDao(); Book category = dao.get(c); System.out.println(category); category.getCategorys().forEach((a)->System.out.println(a)); }*/ }
12.hql
什么是hql
HQL是Hibernate Query Language(Hibernate 查询语言)的缩写,提供更加丰富灵活、更为强大的查询能力;HQL更接近SQL语句查询语法。Hibernate 查询语言(HQL)是一种面向对象的查询语言,类似于 SQL,但不是去对表和列进行操作,而是面向对象和它们的属性。 HQL 查询被 Hibernate 翻译为传统的 SQL 查询从而对数据库进行操作。
HQL | SQL |
---|---|
类名/属性 | 表名/列名 |
区分大小写,关键字不区分大小写 | 不区分大小写 |
?,从下标0开始计算位置 ,(高版本的不再支持?) | ?,从顺序1开始计算位置 |
:命名参数 | 不支持:命名参数 |
面向对象的查询语言 | 面向结构查询语言 |
注:
注1:QuerySyntaxException:XXX is not mapped
原因:
1)在hql中类名写错,注意区分大小写
2)对应的类没有编写hibernate映射文件
3)编写的映射文件但没有将映射文件加入到核心配置文件
实例
package my;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.junit.Test;
import com.zking.hibernate.entity.User;
import com.zking.hibernate.utils.GetSession;
public class HqlDemp {
//查询全部
@Test
public void selectAll() {
// 可以简写为from User u
String hql="from User u";
//String hql="select u from User u";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
List<User> list = query.list();
GetSession.closeSession();
list.forEach((a)->System.out.println(a));
}
//带where语句的查询
@Test
public void selectAllWhere() {
String hql="from User u where u.userName like :name";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
query.setParameter("name", "z%");
List<User> list = query.list();
GetSession.closeSession();
list.forEach((a)->System.out.println(a));
}
//查询单条(如果数据库有多条的话会报错)
@Test
public void selectone() {
String hql="from User u where u.id=:id";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
query.setParameter("id", 1);
User user = (User)query.uniqueResult();
System.out.println(user);
GetSession.closeSession();
}
//返回Object[]
@Test
public void selectObjects() {
String hql="select u.userName,u.userPwd from User u where u.userName = :name";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
query.setParameter("name", "zs");
List<Object[]> list = query.list();
GetSession.closeSession();
list.forEach((a)->System.out.println(Arrays.toString(a)));
}
//返回Map
@Test
public void selectMap() {
String hql="select new Map(u.userName as 名字,u.userPwd as 密码) from User u where u.userName = :name";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
query.setParameter("name", "zs");
List<Map<String, Object>> list = query.list();
GetSession.closeSession();
list.forEach((a)->System.out.println(a.get("名字")+"\t"+a.get("密码")));
}
}
@Test
public void ls() {
String hql="SELECT new Map( t1.orderNo as 订单编号,t2.quantity as 订单排序) FROM TOrder t1 INNER JOIN TOrderItem t2 on t1.orderId =t2.TOrder.orderId WHERE t1.orderId=1";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
List<Map<String, Object>> list = query.list();
list.forEach((a)->System.out.println(a));
GetSession.closeSession();
}
//*一般的话这个是使用配置文件配置的属性。如果没有配置oid的话会一直报文件不能解析
@Test
public void ls() {
String hql="SELECT new Map( t1.orderNo as 订单编号,t2.quantity as 订单排序) FROM TOrder t1 INNER JOIN TOrderItem t2 on t1.orderId =t2.oid WHERE t1.orderId=1";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
List<Map<String, Object>> list = query.list();
list.forEach((a)->System.out.println(a));
GetSession.closeSession();
}
@Test
public void ls() {
String hql="SELECT new Map( t1.orderNo as 订单编号,t2.quantity as 订单排序) FROM TOrder t1 INNER JOIN TOrderItem t2 on t1 =t2.TOrder WHERE t1.orderId=1";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
List<Map<String, Object>> list = query.list();
list.forEach((a)->System.out.println(a));
GetSession.closeSession();
}
//使用聚合函数(使用多是一样的,这边就拿sum举例子)
@Test
public void ls() {
String hql="SELECT new Map( t1.orderNo as 订单编号,sum(t2.quantity) as 订单排序总数) FROM TOrder t1 INNER JOIN TOrderItem t2 on t1 =t2.TOrder WHERE t1.orderId=1";
Session session = GetSession.getSession();
Query query = session.createQuery(hql);
List<Map<String, Object>> list = query.list();
list.forEach((a)->System.out.println(a));
GetSession.closeSession();
}
13.缓存
-
为什么要缓存
-
用缓存,主要有两个用途:高性能、高并发。
高性能:非实时变化的数据-查询mysql耗时需要300ms,存到缓存中,每次查询仅仅1ms,性能瞬间提升百倍。
高并发:mysql 单机支撑到2K QPS就容易报警了,如果系统中高峰时期1s请求1万,仅单机mysql是支撑不了的,但是使用缓 存的话,单机支撑的并发量轻松1s几万~十几万。原因是缓存位于内存,内存对高并发的良好支持。
-
什么数据需要使用缓存
- 很少被修改或根本不改的数据
- 使用频率高的数据
业务场景比如:耗时较高的统计分析sql、电话账单查询sql等
-
最经典的缓存+数据库读写的模式,就是 Cache Aside Pattern。
- 读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
- 更新的时候,先更新数据库,然后再删除缓存。
如何保证数据库与缓存一致
-
非高并发
先修改数据库,再删除缓存。如果缓存删除失败,导致缓存中是旧数据。而数据库上面的是新数据
解决办法:
先删除缓存,在修改数据库。如果删除缓存失败,那么整个都失败。如果是修改时报错。那么下一次读取数据的时候,虽然都是旧数据,但是保持了数据的一致性
-
高并发
先删除了缓存,然后要去修改数据库,此时还没修改。(定义为步骤A)
一个请求过来,去读缓存,发现缓存空了,去查询数据库(定义为步骤B1)。查到了修改前的旧数据,放到了缓存中。(定义为步骤B2)
随后数据变更的程序完成了数据库的修改。此时数据库和缓存数据不一致了。
解决方法:
定义一个FIFO的阻塞队列,例如:LinkedBlockingQueue,将步骤A和步骤B放入同一个队列中。步骤A必然在步骤B的前面。
当场景发生了上述步骤B1时,只有2个情况:缓存已删除,数据库已修改或者数据库还未修改。不考虑已修改的正常情况,则步骤A必然已发生。
则可以在,步骤A和步骤B1发生时均按照数据唯一标识(ID)入同一个队列。步骤A先于步骤B1入队,按照FIFO的方式,步骤A会先完成,则问题
理论上得以解决。注意事项:
-
14.eacache
-
eacache是什么:
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
注1:本章介绍的是2.X版本,3.x的版本和2.x的版本API差异比较大
-
导入依赖
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.0</version> </dependency>
-
实例
package com.zking.hibernatedemo2.utils; import java.io.InputStream; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; public final class EhcacheUtil { private static CacheManager cacheManager; static { try { InputStream is = EhcacheUtil.class.getResourceAsStream("/ehcache.xml"); cacheManager = CacheManager.create(is); } catch (Exception e) { throw new RuntimeException(e); } } private EhcacheUtil() { } public static void put(String cacheName, Object key, Object value) { Cache cache = cacheManager.getCache(cacheName); if (null == cache) { //以默认配置添加一个名叫cacheName的Cache cacheManager.addCache(cacheName); cache = cacheManager.getCache(cacheName); } cache.put(new Element(key, value)); } public static Object get(String cacheName, Object key) { Cache cache = cacheManager.getCache(cacheName); if (null == cache) { return null; } Element element = cache.get(key); return null == element ? null : element.getValue(); } public static void remove(String cacheName, Object key) { Cache cache = cacheManager.getCache(cacheName); if (null == cache) { System.out.println("移除了"); return; } cache.remove(key); }
使用
public class EhcacheUtilTest { @Test public void test() { User user = new User(); user.setId(1); user.setUserName("admin"); user.setRealName("管理员"); System.out.println("放入缓存"); EhcacheUtil.put("stuCache", "user001", user); User u = (User)EhcacheUtil.get("stuCache", "user001"); System.out.println("从缓存中获取"+u); } }
14.hibernate集成ehcache
1. 在原有的的环境上导入jar包
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.4.10.Final</version>
</dependency>
-
配置文件
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> <!--磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存--> <!--path:指定在硬盘上存储对象的路径--> <!--java.io.tmpdir 是默认的临时文件路径。 可以通过如下方式打印出具体的文件路径 System.out.println(System.getProperty("java.io.tmpdir"));--> <diskStore path="java.io.tmpdir"/> <!--defaultCache:默认的管理策略--> <!--eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断--> <!--maxElementsInMemory:在内存中缓存的element的最大数目--> <!--overflowToDisk:如果内存中数据超过内存限制,是否要缓存到磁盘上--> <!--diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false--> <!--timeToIdleSeconds:对象空闲时间(单位:秒),指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问--> <!--timeToLiveSeconds:对象存活时间(单位:秒),指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问--> <!--memoryStoreEvictionPolicy:缓存的3 种清空策略--> <!--FIFO:first in first out (先进先出)--> <!--LFU:Less Frequently Used (最少使用).意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存--> <!--LRU:Least Recently Used(最近最少使用). (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存--> <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/> <!--name: Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里)--> <cache name="com.zking.hibernatedemo2.entity.TSysTreeNode" eternal="false" maxElementsInMemory="100" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/> </ehcache>
-
hibernate的配置核心配置文件
<?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> <property name="connection.username">root</property><!-- 连接的name --> <property name="connection.password">123456</property><!-- 连接的密码 --> <property name="connection.url">jdbc:mysql://localhost:3306/westos?useUnicode=true&characterEncoding=utf-8&useSSL=false</property><!--url --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property><!--驱动程序 --> <!-- mysql方言 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <!--显示sql语句 --> <property name="format_sql">true</property><!-- 使显示的sql语句格式化,更方便查看--> <!-- 开启二级缓存 --> <property name="hibernate.cache.use_second_level_cache">true</property> <!-- 开启查询缓存 --> <property name="hibernate.cache.use_query_cache">true</property> <!-- EhCache驱动 --> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <!-- 映射文件 --> <mapping resource="mapping/Torder.hbm.xml"/> <mapping resource="mapping/Torderitem.hbm.xml"/> <mapping resource="mapping/TSysTreeNode.hbm.xml"/> <!-- 多对多 --> <mapping resource="mapping/Category.hbm.xml"/> <mapping resource="mapping/Book.hbm.xml"/> </session-factory> </hibernate-configuration>
-
实体配置文件的配置(配置关联的需要在关联的里面设置)
<?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"> <!-- Generated 2020-8-2 17:12:03 by Hibernate Tools 4.3.5.Final --> <hibernate-mapping> <class name="com.zking.hibernatedemo2.entity.TSysTreeNode" table="t_sys_tree_node" catalog="westos" optimistic-lock="version"> <cache usage="read-only" /> <!-- --> <id name="treeNodeId" type="java.lang.Integer"> <column name="tree_node_id" /> <generator class="increment" /> </id> <property name="treeNodeName" type="string"> <column name="tree_node_name" length="50" not-null="true" /> </property> <property name="treeNodeType" type="int"> <column name="tree_node_type" not-null="true" /> </property> <property name="position" type="java.lang.Long"> <column name="position" /> </property> <property name="url" type="string"> <column name="url" length="1024" /> </property> <many-to-one name="TSysTreeNode" class="com.zking.hibernatedemo2.entity.TSysTreeNode" > <column name="parent_node_id" /> </many-to-one> <!--set方式 --> <!-- <set name="TSysTreeNodes" table="t_sys_tree_node" inverse="false" cascade="save-update"> <key> <column name="parent_node_id" /> </key> <one-to-many class="com.zking.hibernatedemo2.entity.TSysTreeNode" /> </set> --> <!-- list 按指定的order-by条件进行排序,注意:条件中是列名而不是属性名--> <bag name="childNodes" inverse="false" cascade="save-update" order-by="position asc"> <cache usage="nonstrict-read-write" region="com.zking.hibernatedemo2.entity.TSysTreeNode.childNodes"/> <key column="parent_node_id"/> <one-to-many class="com.zking.hibernatedemo2.entity.TSysTreeNode"/> </bag> </class> </hibernate-mapping>
5.测试
@Test
public void s() {
Session session = GetSession.getSession();
String hql="SELECT t FROM TSysTreeNode t";
Query query = session.createQuery(hql);
query.setCacheable(true);
List list = query.list();
list.forEach((a)->System.out.println(a));
GetSession.closeSession();
System.out.println("------------------------------------------------------");
Session session1 = GetSession.getSession();
String hql1="SELECT t FROM TSysTreeNode t";
Query query1 = session1.createQuery(hql1);
query1.setCacheable(true);
List list1 = query1.list();
list1.forEach((a)->System.out.println(a));
GetSession.closeSession();
}