~1、Mybatis
Mybatis
转载链接:https://blog.csdn.net/qq_32166627/article/details/70741729
1、读取配置信息创建SqlSessionFactory:会话工厂-SqlSessionFactoryBuilder().build方法创建SqlSessionFactory
2、创建SqlSession:包含操作数据库的接口-SqlSessionFactory.openSession()创建一个SqlSession
3、SqlSession底层的Excutor执行器接口操作数据库:两个实现类一个普通执行器、一个缓存执行器(默认)
4、MappedStatement对象包含:Sql语句,输入参数映射信息,输出结果集映射信息,包含java基本类型、hashmap、pojo对象类型。
什么是springboot
用来简化spring应用的初始搭建以及开发过程 使用特定的方式来进行配置(properties或yml文件)
创建独立的spring引用程序 main方法运行
嵌入的Tomcat 无需部署war文件
简化maven配置
自动配置spring添加对应功能starter自动化配置
springboot常用的starter有哪些
spring-boot-starter-web 嵌入tomcat和web开发需要servlet与jsp支持
spring-boot-starter-data-jpa 数据库支持
spring-boot-starter-data-redis redis数据库支持
spring-boot-starter-data-solr solr支持
mybatis-spring-boot-starter 第三方的mybatis集成starter
springboot自动配置的原理
在spring程序main方法中 添加@SpringBootApplication或者@EnableAutoConfiguration
会自动去maven中读取每个starter中的spring.factories文件 该文件里配置了所有需要被创建spring容器中的bean
springboot集成mybatis的过程
添加mybatis的starter maven依赖
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.2.0
在mybatis的接口中 添加@Mapper注解
在application.yml配置数据源信息
springboot如何添加【修改代码】自动重启功能
添加开发者工具集=====spring-boot-devtools
~2、hibernate
mybatis:缓存-session,mapper,第三方
hibernate:session-sessionfactory 都是从小到大,该session对应语句而不是会话。
inverse&cascade
inverse(反转,倒转的)
inverse的值是boolean值,也就是能设置为true或false。 如果一方的映射文件中设置为true,说明在映射关系(一对多,多对多等)中让对方来维护关系。如果为false,就自己来维护关系。默认值是true。 并且这属性只能在一端设置。比如一对多,这个一端。也就是在有set集合的这方设置。
1、也就是维护外键的关系了,通俗点讲,就是哪一方去设置这个被外键约束的字段的值。
2、维护级联的关系,也就是说如果如果让对方维护关系,则自己方的级联将会失效,对方设置的级联有用,如果自己维护关系,则自己方的级联会有用,但是对方设置的级联就会失效。
cascade(级联)关系
级联,就是对一个对象进行操作的时候,会把他相关联的对象也一并进行相应的操作,相关联的对象意思是指 比如班级跟学生,Student的实体类中,存在着Classes对象的引用变量,如果保存Classes对象的引用变量有值的话,则该值就是相关联的对象,并且在对student进行save时,如果保存Classes对象的引用变量有值,那么就会将Classes对象也进行save操作, 这个就是级联的作用
到这里,inverse和cascade这两个的作用就已经讲解完了
1、inverse的权限在cascade之上,意思就是cascade是否有用,还得看inverse这个属性
2、inverse的作用:在映射关系中,让其中一方去维护关系,好处就是能提高性能,不用重复维护。维护两种关系,看下
2.1 控制级联关系是否有效
cascade是否有效,就得看inserve的值,如果是自己方来维护关系,那么cascade就有效,反之无效
2.2 控制外键关系
这个就得通过让自己拥有对方的实例引用(可能是set,也可能就是单个存储对象的变量),这样才具备控制外键关系的能力,然后看inserve的值,
3、inverse只能在一的一方设置,并且默认值是true,也就是说,不设置inverse时,默认是让多的一方去维护关系,这种一般是在双向、外键关系中才设置inverse的值,如果是单向的,就只有一方有维护关系的权利。
4、在以后的代码中,先要搞清楚关系,才能写出性能最好的代码。通过学习这两个属性,在测试代码中,就不必那么麻烦了,只需要考虑维护关系的一方,另一方就会自动保存了。
5、如果你对测试代码发送了多少条sql语句不清楚的话,可以往前面看看那篇讲解一级缓存和三种状态的文章,通过快照区和session作用域来分析,到底会发送多少条sql语句。
update&saveOrUpdate的区别
在Hibernate中,最核心的概念就是对PO的状态管理。一个PO有三种状态:
1、未被持久化的VO
此时就是一个内存对象VO,由JVM管理生命周期
2、已被持久化的PO,并且在Session生命周期内
此时映射数据库数据,由数据库管理生命周期
3、曾被持久化过,但现在和Session已经detached了,以VO的身份在运行
这种和Session已经detached的PO还能够进入另一个Session,继续进行PO状态管理,此时它就成为PO的第二种状态了。这种PO实际上是跨了
Session进行了状态维护的。 在传统的JDO1.x中,PO只有前面两种状态,一个PO一旦脱离PM,就丧失了状态了,不再和数据库数据关联,
成为一个纯粹的内存VO,它即使进入一个新的PM,也不能恢复它的状态了。
如果是第一种,则先要save,再update,如果是第二三种则直接update。
saveOrUpdate是用于不知道这个对象是否在Session的生命周期内,此时映射数据库数据,由数据库管理生命周期。如果不是,那么则无法确
认数据库中是否有该对象映射的数据。有可能是刚new出来的呢,肯定不能直接update拉,则需要用saveOrUpdate。
get&loaded的区别
总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,
如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。
区别
1、 查询的时机不一样
get方法任何时刻都是立即加载,只要调用get方法,就马上发起数据库查询。
load方法默认情况下是延迟加载,真正用到对象的非OID字段数据才发起查询。
load方法是可以通过配置的方式改为立即加载。
2、返回的结果不一样
get方法永远返回查询的实体类对象
load方法返回的是代理对象
立即加载:是不管用不用马上查询。
延迟加载:是等到真正用的时候才发起查询。
prv:因为load是延迟加载,使用到代理类的具体方法时如果代理类匹配不到对象肯定报异常,而get只是立刻查,查不到当然直接返回null
不报异常
如何写一个one to many 配置文件
one 的一方
<set name = "多的一方在一的一方的名称(也就是set容器名)" table = "多一方的表名" cascade = "all" lazy = "false" invers = "false">
<key>
<column name = "多的一方的外键名"/>
<key>
<one-to-many class = "多一方类的完整包路径">
</set>
many 的一方
<many-to-onename = "一的一方在多的一方的对象名" class = "一的一方类的完整包路径" fetch = "select" >
<column name = "多的一方的外键名">
<many-to-one>
按照以上配置,即可实现级联操作了。包括级联删除,级联更新。
----------Department.hbm.xml
<?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="cn.hdu.entity.Department" table="DEPARTMENT">
<id name="deptid" column="DEPTID">
<generator class="sequence"><param name="sequence">dept_sequence</param></generator>
</id>
<property name="dname" column="DNAME"></property>
<property name="location" column="LOCATION"></property>
<set name="employees" cascade="save-update" lazy="false">
<key column="DEPTID"></key>
<one-to-many class="cn.hdu.entity.Employee"/>
</set>
</class>
</hibernate-mapping>
-----------Employee.hbm.xml
<?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="cn.hdu.entity.Employee" table="EMPLOYEE">
<id name="empid" column="EMPID">
<generator class="sequence"><param name="sequence">emp_sequence</param></generator>
</id>
<property name="ename" column="ENAME"></property>
<many-to-one name="dept" column="DEPTID" class="cn.hdu.entity.Department" lazy="false"></many-to-one>
</class>
</hibernate-mapping>