【框架】- MyBatis基础
mybatis
-
什么是mybatis
orm的半自动化框架,自己封装了jdbc,创建驱动,创建链接,创建statement等,采取mapper动态代理机制,使使用者只需要关注sql的编写。
mybatis的sql是通过xm或者注解来进行对欲生成的sql进行配置,再通过配置的类路劲反射找到类的对象,从而找到要执行的方法,获取方法中的动态参数, 再将参数根据反射匹配#{}中字符串根据set方法写入到sql中,从而组装成完整的sql在进行执行。最后将执行的结果在映射成对象或者map集合返回回来。
-
mybatis优缺点:
-
优点:
- sql写在文件中可以让sql与代码解析解耦,后期便于维护
- 相对于原生jdbc会减少大量冗余代码
- 采取jdbc来链接数据库,所以会兼容各种数据库
- 便于与spring进行集成
- 提供了映射标签,可以是对象与数据库字段进行映射
-
缺点:
- sql需要自己编写,工程量较大
- sql依赖数据库,所以不便于数据库的迁移
-
-
#{} ${} 区别
- #{} 代表预处理,会将#{}替换成?在调用preparStatement中的set方法进行赋值
- ${} 代表字符串替换,会将${}中的字符直接替换,一般用于表名,关键字等
-
通常一个mapper.xml文件,都会对应一个Dao接口,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
- Dao接口就是Mappper接口,
- dao接口中的全类名就是配置文件中的namesqpce的值
- 接口的方法名对应映射文件中得id值
- 接口的方法参数就是sql的动态参数
- 通过类全名+方法名可以唯一确定映射文件中的对应的执行sql语句
- Dao接口就是Mappper接口,
-
如何进行分页查询,分页插件原理是什么
- 第一中可以直接在sql中编写limit语句
- mybatis是采取RowBounds对象来对返回的结果进行内存分页,而非物理分页,所以一般对于少数据查询可以使用,若是大数据则不推荐使用。
-
Mybatis是否支持延迟加载?如果支持,它的实现原理是什么
- 仅支持association(一对一)和collection(一对多)进行延迟加载通过lazyLoadingEnabled=true|false
- 在调用目标方法时,进行拦截,若是目标方法中不需要获取聚合对象的值,则进行拦截仅查询第一条sql,若是用到聚合对象的值,则在获取第一条sql的返回值来查询第二条sql语句
-
Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式
- 通过resultMap来进行逐一映射数据库列名和对象属性名之间的关系
- 也可以给数据库查询语句中的列定义个别名来进行映射
- 获取映射关系后通过反射来获取对象调用set方法来给对象赋值并返回
-
Mybatis动态sql有什么用?执行原理?有哪些动态sql?
- 动态sql可以在映射文件中以标签形式来编写sql
- 提供的标签有:trim | where | set | foreach | if | choose | when | otherwise | bind、
-
Xml映射文件中,除了常见的select | insert | updae | delete标签之外,还有哪些标签?
标签 定义一个sql片段 有个id属性 标签 可以应用 sql标签的片段sql 标签 定义返回值进行映射配置 定义返回值类型 不支持自增的主键生成策略标签
-
使用MyBatis的mapper接口调用时有哪些要求
- 接口方法名与映射文件mapper.xml中的sql的id 一致
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
- Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
- Mapper.xml文件中的namespace即是mapper接口的类全名路径
-
模糊查询like语句该怎么写
-
直接在sql中写入如下:
// 容易引发sql注入 <select id=”selectlike”> select * from foo where bar like '%${}%' </select>
-
采取传参还有%%方式进行配置:
// 调用方法时直接传参含有%% 比较麻烦 sqlSession.selectList("类路径","%zht%"); <select id=”selectlike”> select * from foo where bar like #{} </select>
-
直接在sql中采取concat进行拼接处理
<select id=”selectlike”> select * from foo where bar like concat('%',#{},'%') </select>
-
-
当实体类中的属性名和表中的字段名不一样 ,怎么办
- 查询语句字段起别名使别名与属性名一致
- 通过
来映射字段名和实体类属性名的一一对应的关系
-
如何获取自动生成的(主)键值
-
insert方法中总会返回一个值,代表插入的行数
-
获取自增主键值可以在标签中配置:usegeneratedkeys=”true”如下:
<insert id=”insertname” usegeneratedkeys=”true” keyproperty=”id”> insert into names (name) values (#{name}) </insert> int rows = mapper.insertname(name); // 完成后,id已经被设置到对象中 system.out.println(“rows inserted = ” + rows); system.out.println(“generated key value = ” + name.getid());
-
-
在mapper中如何传递多个参数
-
直接传递多个参数,sql语句写成#{0},#{1}进行匹配
//DAO层的函数 Public UserselectUser(String name,String area); //对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。 <select id="UserselectUser"resultMap="BaseResultMap"> select * fromuser_user_t whereuser_name = #{0} anduser_area=#{1} </select>
-
直接传递参数,在参数前面协商注解
//DAO层的函数 Public UserselectUser(@param("name") String name, @param("area") String area); //对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。 <select id="UserselectUser"resultMap="BaseResultMap"> select * fromuser_user_t whereuser_name = #{name} anduser_area=#{area} </select>
-
参数封装成map
Map<String, Object> map = new HashMap(); map.put("name", name); map.put("area", area); return sqlSession.selecOne("UserselectUser", map); <select id="UserselectUser"resultMap="BaseResultMap"> select * fromuser_user_t whereuser_name = #{name} anduser_area=#{area} </select>
-
-
一对一、一对多的关联查询
<mapper namespace="com.lcb.mapping.userMapper"> <!--association 一对一关联查询 --> <select id="getClass" parameterType="int" resultMap="ClassesResultMap"> select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id} </select> <resultMap type="com.lcb.user.Classes" id="ClassesResultMap"> <!-- 实体类的字段名和数据表的字段名映射 --> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" javaType="com.lcb.user.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> </resultMap> <!--collection 一对多关联查询 --> <select id="getClass2" parameterType="int" resultMap="ClassesResultMap2"> select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id} </select> <resultMap type="com.lcb.user.Classes" id="ClassesResultMap2"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" javaType="com.lcb.user.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> <collection property="student" ofType="com.lcb.user.Student"> <id property="id" column="s_id"/> <result property="name" column="s_name"/> </collection> </resultMap> </mapper>
-
MyBatis实现一对一/一对多有几种方式?具体怎么操作的
- 有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一/ collection节点配置一对多的类就可以完成
- 嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association/collection配置,但另外一个表的查询通过select属性配置
-
什么是MyBatis的接口绑定?有哪些实现方式
- 接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定
- 实现方式
- 一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定
- 通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名
-
MyBatis与Hibernate有哪些不同
- MyBatis需要程序员自己写sql Hibernate不需要
- Mybatis无法做到数据库无关性如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大 而 Hibernate 可以