1、为什么使用Mybatis框架?
首先框架就是插件(方便我们开发的工具),针对项目中的弊端,进行封装,调试
1、传统的jdbc 的弊端:
1、每次都要获取连接、操作数据、便利结果集、关闭连接(频繁的开启,关闭,浪费资源)
2、SQL语句和代码耦合在一起(不利于程序的维护更新)
3、代码的冗余
4、ORM的(对象关系mapper)好处:
1、代码的繁琐度
2、数据库对象的连接问题
3、系统架构
使用ORM技术,可以将数据库层完全隐蔽,呈献给程序员的只有Java的对象,程序员只需要根据业务逻辑的需要 调 用Java对象的Getter和 Setter方法
5、性能
数据库发送1000次SQL语句执行请求,运行效率较低。
会自动延迟向后台数据库发送SQL请求
只会在循环完成后,一次向数据库发送操作请求,从而大大降低通讯量,提高运行效率;
2、Mybatis 核心配置文件的配置(怎么配,有啥)
(百度在手,天下我有) 1、可以参考mybatis的官网
2、(1)xml约束(dtd,schema)
(2)
<environments default="mysql">
<environment id="mysql">
<!-- 事务管理器 执行的sql单元-->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据库连接 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!--每一个environment可以操作不同的数据库 -->
<!--
<environment id="oracle">
<transactionManager type=""></transactionManager>
<dataSource type=""></dataSource>
</environment>
<environment id="sqlserver">
<transactionManager type=""></transactionManager>
<dataSource type=""></dataSource>
</environment>
-->
</environments>
<!--一定要写,扫描到我们对应的xml文件 -->
<mappers>
<mapper resource="com/offcn/mapper/PersonMapper.xml"></mapper>
</mappers>
总结: 其实就是 ----头+++environments里面的事务、数据源的配置+++Mappers开头的扫描-------------
3、配置结束以后我们怎么使用,怎么读取主配置文件(就是我们怎么使用)
1、创建一个test类,里面有一个 Main 方法,用配置读取,使用mybatis的类
2、读取配置文件
String resource = "mybatiscfg.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
3、通过配置文件实例化工厂
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(inputStream);
4、通过工厂获取session ,传统的不使用代理模式(没有事务),直接再后面写
SqlSession session = sf.openSession();
5、通过session获取接口的代理,(反射,获取代理)
PersonMapper mapper = session.getMapper(PersonMapper.class);
6、操作数据(自己要写的增删改查方法)
PersonMapper mapper = session.getMapper(PersonMapper.class);
Person person1 = new Person();
person1.setPname("张三");
System.out.println(mapper+"====");
mapper.saveInfo(person1);
7、提交事务
session.commit();
8、关闭session
session.close();
代码:
4、关于mybatis的增删改查(CRUD) 简单的demo
1、mapper.xml 里面有对应的.java的地方
<mapper namespace="com.offcn.mapper.CarDetailMapper">
5、关于多个参数的处理(输入数据的出处理,一共四种),哪种更好用
1、数组下表
public int deleteInfo(Integer pid,String pname);
mapper.xml里面直接用数组下标接着#{0}
2、map集合
public int deleteInfo2(Map<String,Object> map);
mapper.xml集合里面
<delete id="deleteInfo2" parameterType="java.util.Map">
delete from person where pid=#{pid} and pname=#{pname}
</delete>
3、使用Param
public int deleteInfo3(@Param("pid") Integer pid, @Param("pname") String pname);
此时直接用我们的pid=#{pid} and pname=#{pname} 接
4、业务模型 传入的参数是一个对象(业务模型 vo)
数据模型: 数据库中的表进行映射
业务模型: 和我们的页面数据进行映射
原理 : 使用查询字段的名称充当我们类中的属性名称,反射获取类型的属性对象,然后给属性对象赋值
pname 获取属性对象(Person name) 也就无法完成赋值,使用了当前对象属性的默认值.
总结:首先选择后面的两个,对于一些数据的封装,以及数据的获取和快捷
6、主键值返回的问题(关于selectKey的操作)、
解决的问题:插入数据后,直接要使用自增长的主键
<insert id="saveInfo" parameterType="com.offcn.bean.Person">
<!-- 主键值 自增长 -->
<!-- <selectKey keyProperty="pid" keyColumn="pid" resultType="int" order="AFTER">
SELECT last_insert_id();
</selectKey>-->
<!-- 主键值是 UUID -->
<selectKey keyProperty="pid" keyColumn="pid" resultType="string" order="BEFORE">
SELECT UUID();
</selectKey>
insert into person(pid,pname) values(#{pid},#{pname})
</insert>
mapper.saveInfo(person);
System.out.println(person.getPid());
之后,直接调用。就可以得到这个值。
总结:selectkey的作用就是 获取主键值。记得order后面的值,表示之前还是之后。
7、参数位置的占位符的两种区别#{} 和 ${} 区别联系
#{} 参数位置被解析称为一个占位符 ? (已经预编译了)
${} 参数的位置被解析成一个字符串的拼接的位置 Statement(静态sql) sql注入风险
concat(${})实现字符串的拼接同时没有sql注入的风险。
8、输出结果映射(resultMap的使用)
resultMap标签 (自定义结果映射):解决的基本的问题是,属性名和表的字段名不一致的问题
我们自己定义了一个查询结果的映射类型
9、多表查询的问题,怎么查,1对1 和1对多,我们怎么去处理
无非就是1对1 用association ,一对多用collection
property: 关联对象属性
column: 提供给级联查询的字段名称
javaType: 结果类型
select : 调用其他工作空间下的查询标签
<resultMap id="newPerson" type="com.offcn.bean.Person">
<id property="pid" column="pid"></id>
<result property="pname" column="pname"></result>
<association property="car" column="pid" javaType="com.offcn.bean.Car" select="com.offcn.mapper.CarMapper.getInfoByPid">
</association>
</resultMap>
resultType: 原生类型
resultMap: 我们自己定义了一个查询结果映射类型
<select id="getInfo" resultMap="newPerson">
select * from person
</select>
下一个表中
<resultMap id="newCar" type="com.offcn.bean.Car">
<id property="cid" column="cid"></id>
<result property="dis" column="dis"></result>
<result property="total" column="total"></result>
//这里是一对多的查询 ofType 和select的书写
<collection property="carDetailList" column="cid" ofType="com.offcn.bean.CarDetail" select="com.offcn.mapper.CarDetailMapper.getInfoByCid">
</collection>
</resultMap>
<select id="getInfoByPid" parameterType="int" resultMap="newCar">
select * from car where p_fk=#{pid}
</select>
总结:这个时候还要注意,我们再实体类中申明一个类,关联对象的私有属性,同时提供set和get的方法
10、动态sql(什么是动态sql),他有哪些标签
1、where if
实例:
<where>
<if test="pid!=null and pid>3">
and pid=#{pid}
</if>
<if test="pname!=null and pname.length()>4">
or pname=#{pname}
</if>
</where>
2、choose(when otherwise)
同上
3、set 标签
替换我们的set标签
必须要传入数据的
set 标签替代set关键字
同时忽略最后一个成立条件后面逗号
4、trim 标签
<trim prefix="where" prefixOverrides="and|or">
<if test="pid!=null and pid>3">
and pid=#{pid}
</if>
<if test="pname!=null and pname.length()>4">
or pname=#{pname}
</if>
</trim>
<trim prefix="set" suffixOverrides=",">
<if test="pname!=null">
pname=#{pname},
</if>
</trim>
总结:使用trim可以替换where 和set,他的效果就是,我们可以做拼接,让我们的sql更灵活
5、foreach标签:批量操作的方法
通过ids这个集合,实现的是批量的删除id,map也是可以的
<delete id="batchDelete" parameterType="com.offcn.bean.PersonVo">
delete from person where pid in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
注意:我们在mysql的批量更新必须要在mysql连接的url中添加一个键值对,允许我们远程批量更新动作
<property name="url" value="jdbc:mysql://localhost:3306/test?allowMultiQueries=true"/>
11、别名是啥,有什么效果,卸载哪里
1、 在我们的mapper.xml中经常使用我们类型的名称(就像我们多表查询中书写表全名,如果表名过于长,需要给表设定 别名) 需要在xml配置文件中添加别名。
2、
<typeAlias type="com.offcn.bean.Person" alias="person"></typeAlias>
<typeAlias type="com.offcn.bean.PersonVo" alias="vo"></typeAlias>
3、 在我们的mapper对应的xml文件中我们可以直接使用类名或者是类名的首字母小写形式
4、 <package name="com.offcn.bean"></package> 加扫描mapper ,更fangbian
12、缓存的效果
1、效果:提高查询效率
2、一级缓存:session默认就是一级缓存 同一个session 使用的数据
3、二级缓存:
<settings>
<setting name="cacheEnabled " value="true"/>
</settings>
mapper.xml
<cache></cache>
当前工厂生产出来的所有的session都可以共享的数据
总结;需要设置三个地方
13、简述一下延时加载(懒加载的工作原理)
1、减少我们的数据库的交互(场景必须是级联查询)
2、
<settings>
<setting name="lazyLoadingEnabled" value="true"></setting>
<setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
3、使用关联对象到时候才会产生我们的关联表的sql语句,按需加载。
14、MBG(逆向工程的使用),需要修改哪些地方,参考那些文档
参考官方文档: mybatis generater,修改
15、Mybatis的注解的使用,怎么用,注意哪些问题
使用注解的形式将sql放入到我们的接口方法上,有效的减少我们的xml的配置(去除掉xml文件)
@Select
@Insert
@update
@delete
@Results
@Result...
//一对多的注解配置
@Select("select * from person where pid=#{pid}")
@Results({
@Result(id = true,property = "pid",column = "pid"),
@Result(property = "pname",column = "pname"),
@Result(property = "car",javaType = List.class,column = "pid",
many =@Many(select = "com.offcn.mapper.CarMapper.getInfosByPid") )
})
Person getOne(Integer pid);
@Results({
@Result(id = true,property = "pid",column = "pid"),
@Result(property = "pname",column = "pname"),
@Result(property = "car",javaType = Car.class,column = "pid",
one = @One(select = "com.offcn.mapper.CarMapper.getInfoByPid"))
})
Person getOne(Integer pid);
16、总结一下mybatis的好处,以及关于mybatis的常见的面试题(百度)
1、持久层框架,解决了jdbc带来的不方便
2、半orm,半sql,
3、支持级联查询,支持缓存机制,懒加载机制
4、条件语句块,可以定义动态sql
5、逆向工程,简化,方便了我们写实体类
6、注解
7、处理结果集,多表查询很方便