目录
##Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
##Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?
##mybatis-plus操作https://blog.youkuaiyun.com/fhefhffg/article/details/122324051#t83
什么是mybatis
持久层框架, 它内部封装了 JDBC,简化了JDBC的操作方式,是一个半 ORM框架:Mybatis在查询 关联对象或关联集合对象 时,需要手动编写sql来完成,所以,称之为半自动ORM框架。##为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
什么是mybatis-plus
是MyBatis的增强工具
其中应用到了ORM思想,即以对象的方式操作数据库(对象关系映射)
ORM思想
用于实现 不同系统的数据 之间的转换
#Mybatis的工作流程
Mybatis的工作原理 lpx
1, mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件
(也可以用Java文件配置的方式,需要添加@Configuration)中构建出SqlSessionFactory(SqlSessionFactory是线程安全的)————创建SqlSessionFactory
2, SqlSessionFactory的实例直接开启一个SqlSession————通过SqlSessionFactory创建SqlSession
3, 再通过SqlSession实例获得Mapper对象 并 执行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交(通过SqlSession执行数据库操作 调用session.commit()提交事务 调用session.close()关闭事务)
4, 关闭SqlSession
说明:SqlSession是单线程对象,因为它是非线程安全的,是持久化操作的独享对象,类似jdbc中的Connection,底层就封装了jdbc连接。
##Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
答:
第一种是使用<resultMap>标签,列名和对象属性名逐一映射。
第二种是使用sql的列别名功能,列别名和对象属性名逐一映射。
Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回
,那些找不到映射关系的属性,是无法完成赋值的。
-----比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。
#resulttype和resultmap区别
mybatis单表查询:
1、当表中的字段与POJO中的属性名称一致时,映射文件中使用resultType进行映射
2、当表中的字段与POJO中的属性名称不一致时,不能直接使用resultType进行映射,需要使用resultMap进行映射.
mybatis多表关联查询:
映射文件中使用resultMap进行映射
多表关联查询
MyBatis中resultType和resultMap的区别
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的(对应着我们的model对象中的实体),而resultMap则是对外部ResultMap的引用(提前定义了db和model之间的隐射key:value关系),但是resultType跟resultMap不能同时存在。
在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。
(1)当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性是resultType的时候,MyBatis对自动的给把对应的值赋给resultType所指定对象的属性。
(2)当提供的返回类型是resultMap时,因为Map不能很好表示领域模型,就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。
##Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?
Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?
不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配
置 namespace,那么 id 不能重复;
原因就是 namespace+id 是作为 Map<String, MapperStatement>的 key
使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。
有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然
也就不同。
##通常一个 Xml 映射文件,都会写一个 Dao/mapper 接口与之对应,
请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法,
参数不同时,方法能重载吗? //使用MyBatis的mapper接口调用时有哪些要求?//
1、映射文件中的 namespace 是 mapper 层接口的全路径。
2、映射文件中 每个 sql 的id 是 Mapper层接口方法名 ;
3、映射文件中 每个 sql 的 parameterType 的类型 是 Mapper 层接口方法的输入参数类型 ;
----------用户传进来的值
4、映射文件中 每个 sql 的 resultType 的类型 是 Mapper 接口方法的输出参数类型;
----------返回给用户的值
Dao 接口即 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值;
接口的方法名,就是映射文件中 Mapper 的 Statement 的 id 值;接口方法内的
参数,就是传递给 sql 的参数。
Mapper 接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符
串作为 key 值,可唯一定位一个 MapperStatement。在 Mybatis 中,每一个
<select>、<insert>、<update>、<delete>标签,都会被解析为一个
MapperStatement 对象。
Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
Mapper.xml文件中的namespace即是mapper接口的类路径
mapper.xml文件中定义的每个sql的id和Mapper接口方法名相同
##什么是MyBatis的接口绑定,有什么好处?有哪些实现方式?
接口映射就是把接口里面的方法和SQL语句绑定,我们通过直接调用接口方法就可以
,这样比起原来了 SqlSession 提供的方法我们可以有更加灵活的选择和设置
有哪些实现方式?
接口绑定有两种实现方式,
一种是通过注解绑定,就是在接口的方法上面加上
@Select、@Update 等注解,里面包含 Sql 语句来绑定;
另外一种就是通过 映射文件
里面写 SQL 来绑定, 在这种情况下,要指定 xml 映射文件里面的 namespace 必须
为接口的全路径名。当 Sql 语句比较简单时候,用注解绑定, 当 SQL 语句比较复杂
时候,用 xml 绑定,一般用 xml 绑定的比较多。
举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯
一找到 namespace 为 com.mybatis3.mappers.StudentDao 下面 id 为
findStudentById 的 MapperStatement。
Mapper 接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻
找策略。Mapper 接口的工作原理是 JDK 动态代理,Mybatis 运行时会使用 JDK
动态代理为 Mapper 接口生成代理对象 proxy,代理对象会拦截接口方法,转而
执行 MapperStatement 所代表的 sql,然后将 sql 执行结果返回。
#动态sql
##什么是动态sql
简单地讲就是通过不同的判断条件执行不同的sql语句就是动态sql
##都有哪些动态sql?什么时候使用、怎么使用
Mybatis提供了9种动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind。
在对象中的数据不为空的前提下进行查询,将对象中的数据不为空当作where条件
可以使用where+if标签动态查询
where标签 作用:去除where后边多余的一个and/or
如果不想使用所有的条件,只需要满足其中一个条件时
可以使用where+choose、when、otherwise标签分支结构动态查询-相当于java中的if-else语法
在对象中的数据不为空的前提下进行修改,将对象中的数据不为空当作set条件
可以使用set+if标签动态修改
set标签 作用:去除set后边多余的,号
##MyBatis应用动态SQL解决了什么问题
有时候,固定的sql语句不能够满足我们的应用需求。这个时候需要在 标准的基础上建立动态的查询语句。
Mybatis提供了多种注解,可以提供动态查询语言。
比如说在开发的时候,遇到这样的场景,界面提供了多种查询,但是都是非 必填写,在选择查询条件时可以选中任意几种组合作为查询条件,如果在使 用jdbc的时候,需要判断参数为空,自己组装sql,
但是mybatis提供动态sql机制,依靠标签。
在开发的时候,查询的内容但是都是非 必填写 可能为空,有时候不写内容也可以进行查询;
如果使 用jdbc,需要判断数据是否为空,自己组装sql;但是使用动态SQL时,只需要依靠标签即可。
#Mybatis 中#和$的区别--面试
相同点:都是通过get来获取值的
不同点:
#{} 是占位符,预编译处理。 ${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
使用#{}可以有效的防止SQL注入。----如:where name=#{name} 如果传入的值是jack,那么解析成的SQL是:where name="jack"
Mybatis在处理${}时,就是把${}替换成变量的值。
#数据库连接JDBC
csdn-下载-JDBC连接数据库进行增删改查下载位置
##什么是jdbc 面试
专门用来完成java和数据库交互的的技术
##JDBC连接数据库的步骤 面试
1.注册驱动
2.获取连接:连接数据库,并返回了数据库的连接Connection
3.获取传输器:创建一个Statement语句对象
4.执行SQL语句
5.处理结果集
6.释放资源-close()方法
##什么是SQL攻击/注入-举例说明sql注入问题--面试
###什么是SQL注入/攻击
程序开发过程中没有规范书写 sql 语句和对特殊字符进行过滤,导致客户端通过 POST 和 GET 提交一些 恶意的sql 语句也能正常执行,而不是按照设计者意图去执行SQL语句。
###例子
比如SQL中出现了特殊符号,比如#,#号在SQL中是注释的意思(测试时使用固定的用户名jack’#;密码输几个空格也能登陆成功)
传输器在执行SQL时遇到了SQL拼接,把#当做了注释用!
###防止 SQL 注入的方式 信省滤巧(信胜率巧)
1、永远不要相信用户的输入,可以通过正则表达式对用户的输入进行校验,或限制长度,对单引号和双"-"进行转换等。
2、Sql 语句书写尽量不要省略双引号和单引号。
3、过滤掉 sql 语句中的一些关键词:update、insert、delete、select、 * 。
4、提高数据库表和字段的命名技巧,对一些重要的字段根据程序的特点命名,取不易被猜到的
永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。
永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。
应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中。
#JDBC和Mybatis区别
JDBC:
数据库创建连接、释放频繁造成系统资源浪费
Sql语句写在代码中不易维护,向sql语句传参数麻烦
处理结果集麻烦,sql变化导致解析代码变化,且解析前需要遍历
MyBatis:
使用连接池管理数据库链接
Sql语句写在XXXXmapper.xml文件中与代码分离
Mybatis自动将java对象映射至sql语句,自动将sql执行结果映射至java对象
JDBC代码相对繁琐但访问速度更快,比如使用JDBC批处理等方式效率比Mybatis要高。
#Mybatis 缓存
如果相同的数据需要多次查询,则可以使用缓存的方式处理,提高用户的响应速度
##mybatis一二级缓存
通过SqlSessionFactory获取SqlSession
SqlSession的理解:就是数据库连接+传输器对象 的封装体
一级缓存: 默认开启
SqlSession级别 的共享/缓存
在同一个sqlSession内实现数据的共享(单线程操作下的多次查询)
// 理解:一个人用同一个链接/方法 进行多次相同的查询,只查一次(一个人多次查询同样的东西)——单线程操作下的多次查询
一级缓存的生命周期和SqlSession一致,当有多个SqlSession或者分布式环境下,数据库写操作会引起脏数据。
二级缓存: 默认开启 +但是需要我们配置才能正常使用
SqlSessionFactory级别的共享/缓存
在一个sqlSessionFactory内,实现不同SqlSession 数据共享(多线程)
理解:(多个不同的人查询同样的东西)——并发性问题,所以对象必须序列化
//共享的理解:100个人同时查询同一个数据库,第一个人来的时候,查询一次数据库,直接把第一个人查到的结果返回;剩下的99个人就不查了。效率高
当开启缓存后,数据查询的执行的流程是:二级缓存>一级缓存>数据库
#如何分页操作
##mybatis-plus分页操作https://blog.youkuaiyun.com/fhefhffg/article/details/122324051#t83
MybatisPlus如果需要使用分页, 需要一个编辑配置类 额外的指定数据库版本.
之后使用mybatise-plus 分页 的固定API new Page<>(current, size)分页对象进行分页操作
mybatis-plus分页说明
* 1.new Page<>(current, size);
* current:当前页数
* size: 每页条数
*/
@Override
public EasyUITable findItemByPage(Integer page, Integer rows) {
Page<Item> tempPage = new Page<>(page, rows);
QueryWrapper<Item> queryWrapper = new QueryWrapper<Item>();
queryWrapper.orderByDesc("updated");
//当前查询的分页结果对象
IPage<Item> IPage =
itemMapper.selectPage(tempPage, queryWrapper);
//获取总记录数
int total = (int) IPage.getTotal();
//获取分页的结果
List<Item> userList = IPage.getRecords();
return new EasyUITable(total, userList);
}
@Configuration //配置类
public class MybatisConfig {
/* <bean id="paginationInterceptor" class=""/> */
//添加分页拦截器,否则分页有问题!!!!
@Bean //将对象交给Spring容器管理
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
##mybatis分页操作
Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。
可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect(方言)添加对应的物理分页语句和物理分页参数。