简介
作用
底层是对JDBC的封装
优点
使用 mybatis 时不需要编写实现类,只需要写需要执行的sql命令
环境搭建
jar
- jstl
- log4j
- mybatis
- mysql-connector
全局配置文件
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="default">
<environment id="default">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="xxxxxxx"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/LogMapper.xml"></mapper>
</mappers>
</configuration>
mapper配置文件
文件作用: 编写需要执行的 SQL 命令
把 xml 文件理解成实现类.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.LogMapper">
<select id="selByAccinAccount" resultType="pojo.Log">
</select>
</mapper>
单独使用mybatis时的执行方法
InputStream is = Resources.getResourceAsStream("myabtis.xml");
//使用工厂设计模式
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//生产 SqlSession
SqlSession session=factory.openSession();
//a.b为命名空间
List<Flower> list = session.selectList("a.b.selAll");
for (Flower flower : list) {
System.out.println(flower.toString());
}
session.close();
三种查询方式
- selectList() 返回值为 List<resultType 属性控制>
- selectOne() 返回值 Object
- selectMap() 返回值 Map
路经相关问题
- 编写路径为了告诉编译器如何找到其他资源.
- 路径分类
-
相对路径:从当前资源出发找到其他资源的过程
-
绝对路径:从根目录(服务器根目录或项目根目录)出发找到其他资源的过程
注意:只要以/开头的都是绝对路径
- 绝对路径
- 如果是请求转发 / 表示项目根目录(WebContent)
- 其他重定向,
- 如果客户端请求的控制器,控制器转发到JSP后,jsp中如果使用相对路径,需要按照控制器的路径去找其他资源.
使用绝对路径,可以防止上面的问题.
log4j(日志)
作用:不仅能把内容输出到控制台,还能把内容输出到文件中.便于观察结果.
使用步骤
- 导入log4j-xxx.jar
- 在src下新建log4j.properties(路径和名称都不允许改变)
log4j.appender.LOGFILE.File 文件位置及名称(日
志文件扩展名.log)log4j关联mapper的namespace
log4j.rootCategory=DEBUG, CONSOLE ,LOGFILE log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppend er log4j.appender.CONSOLE.layout=org.apache.log4j.Patter nLayout log4j.appender.CONSOLE.layout.ConversionPattern=%C %d{ YYYY-MM-dd hh:mm:ss} %m %n log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=D://logs/my.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.Patter nLayout log4j.appender.LOGFILE.layout.ConversionPattern=%C %m %L %n
在mybatis中使用log4j
<settings> <setting name="logImpl" value="LOG4J"/> </settings>
parameterType属性
- 在 XXXMapper.xml 中等标签的 parameterType 可以控制参数类型
- SqlSession的selectList()和selectOne()的第二个参数和selectMap()的第三个参数都表示方法的参数,例:
People p = session.selectOne("a.b.selById",1); System.out.println(p);
在 Mapper.xml 中可以通过#{}获取参数,使用索引,从 0 开始 #{0}表示第一个参数
#{} 和 ${} 的区别
#{} 获取参数的内容支持 索引获取,param1 获取指定位置参数, 并且 SQL 使用?占位符。
- 使用索引,从 0 开始 #{0}表示第一个参数
- 如果参数是对象#{属性名}, 如果参数是 map 写成#{key}
-
字
符
串
拼
接
不
使
用
?
,
默
认
找
{} 字符串拼接不使用?,默认找
字符串拼接不使用?,默认找{内容}内容的 get/set 方法,如
果写数字,就是一个数字
typeAliases别名
给某个类起别名
示例
<typeAliases> <typeAlias type="com.bjsxt.pojo.People" alias="peo"/> </typeAliases>
mapper.xml
<select id="page" resultType="peo" parameterType="map"> select * from people limit #{pageStart},#{pageSize} </select>
给某个包下所有类起别名,别名为类名,不区分大小写
mtbatis.xml
<typeAliases> <package name="com.bjsxt.pojo" /> </typeAliases>
mapper.xml
<select id="page" resultType="People" parameterType="map"> select * from people limit #{pageStart},#{pageSize} </select>
小结
- 在 mybatis 中默认是关闭了 JDBC 的自动提交功能
- JDBC 中 executeUpdate()执行新增,删除,修改的 SQL.返回值 int, 表示受影响的行数.
- mybatis 中 标签没有 resultType 属性, 认为返回值都是 int
- 如果出现异常,应该 session.rollback()回滚事务
Mybatis实现新增
1. 概念复习
1.1 功能:从应用程序角度出发,软件具有哪些功能.
1.2 业务:完成功能时的逻辑.对应 Service 中一个方法
1.3 事务:从数据库角度出发,完成业务时需要执行的 SQL 集合,统称一个事务.
事务回滚.如果在一个事务中某个 SQL 执行事务,希望回
归到事务的原点,保证数据库数据的完整性.2.关于自动提交
在 mybatis 中默认是关闭了 JDBC 的自动提交功能
2.1 每一个 SqlSession 默认都是不自动提交事务.
2.2 session.commit()提交事务.
2.3 openSession(true);自动提交.setAutoCommit(true);
3.关于底层封装
mybatis 底层是对 JDBC 的封装.
3.1 JDBC 中 executeUpdate()执行新增,删除,修改的 SQL.返回值 int, 表示受影响的行数.
3.2 mybatis 中 标签没有 resultType 属性, 认为返回值都是 int
4.在 openSession()时 Mybatis 会创建 SqlSession 时同时创建一个Transaction(事务对象),同时 autoCommit 都为 false
如果出现异常,应该 session.rollback()回滚事务
新增
<insert id="ins" parameterType="People"> insert into people values(default,#{name},#{age}) </insert>
int index1 = session.insert("a.b.ins", p); if(index1>0){ System.out.println("成功"); session.commit(); } else{ System.out.println("失败"); session.rollback(); }
修改
<update id="upd" parameterType="People"> update people set name = #{name} where id = #{id} </update>
删除
<delete id="del" parameterType="int"> delete from people where id = #{0} </delete>
接口绑定方案及多参数传递
实现创建一个接口后把mapper.xml由mybatis 生成接口的实现类,通过调用接口对象就可以获取 mapper.xml 中编写的 sql。
实现步骤:
创建一个接口
- 接口包名和接口名与mapper.xml中namespace相同
- 接口中方法名和 mapper.xml 标签的 id 属性相同
在 mybatis.xml 中使用进行扫描接口和mapper.xml
代码实现步骤
在 mybatis.xml 中下使用
<mappers> <package name="mapper"/> </mappers>
在 mapper 下新建接口
public interface LogMapper { List<Log> selAll(); }
在mapper 新建一个 xxxMapper.xml
- namespace 必须和接口全限定路径(包名+类名)一致
- id 值必须和接口中方法名相同
- 如果接口中方法为多个参数,可以省略 parameterType
<mapper namespace="mapper.LogMapper"> <select id="selAll" resultType="log"> select * from log </select> </mapper>
多参数实现方法
在接口中声明方法
List<Log> selByAccInAccout(String accin,String accout);
在mapper.xml中添加
- #{}中使用 0,1,2 或 param1,param2
<!-- 当多参数时,不需要写 parameterType --> <select id="selByAccInAccout" resultType="wz.pojo.Log" > select * from log where accin=#{0} and accout=#{1} </select>
- 使用注解方法
/** * mybatis 把参数转换为 map 了,其中@Param("key") 参数内 容就是 map 的 value * @param accin123 * @param accout3454235 * @return */ List<Log> selByAccInAccout(@Param("accin") String accin123,@Param("accout") String accout3454235);
mapper.xml文件
<!-- 当多参数时,不需要写 parameterType --> <select id="selByAccInAccout" resultType="wz.pojo.Log" > select * from log where accin=#{accin} and accout=#{accout} </select>
动态SQL(很实用)
- 根据不同的条件需要执行不同的 SQL 命令.称为动态 SQL
- MyBatis 中动态 SQL 在 mapper.xml 中添加逻辑判断等.
- if使用
<select id="selByAccinAccout" resultType="wz.pojo.Log"> select * from log where 1=1 <!-- OGNL表达式 --> <if test="accIn!=null and accIn!=''"> and accin=#{accIn} </if> <if test="accOut!=null and accOut!=''"> and accout=#{accOut} </if> </select>
- 当编写 where 标签时,如果内容中第一个是 and 去掉第一个
and - 如果中有内容会生成 where 关键字,如果没有内容不
生成 where 关键字
<select id="selByAccinAccout" resultType="wz.pojo.Log"> select * from log <where> <!-- OGNL表达式 --> <if test="accIn!=null and accIn!=''"> and accin=#{accIn} </if> <if test="accOut!=null and accOut!=''"> and accout=#{accOut} </if> </where> </select>
比直接使用少写 where 1=1
- 用在修改 SQL 中 set 从句
- 去掉最后一个逗号
- 如果里面有内容生成 set 关键字,没有就不生成
实例
<update id="upd" parameterType="wz.pojo.Log"> update log <set> id=#{id}, <if test="accIn!=null and accIn!=''"> accin=#{accIn}, </if> <if test="accOut!=null and accOut!=''"> accout=#{accOut}, </if> </set> where accin=#{accIn} </update>
- Trim
- prefix 在前面添加内容
- prefixOverrides 去掉前面内容
- suffix 在后面添加内容
- suffixOverrieds 去掉后面内容
- 执行顺序去掉内容后添加内容
<select id="selByLog" parameterType="wz.pojo.Log" resultType="wz.pojo.Log"> select * from log <trim prefix="where" prefixOverrides="and"> and accin=#{accIn} </trim> </select>
- bind
- 作用:给参数重新赋值
- 使用场景:1.模糊查询 2.在原内容前后添加内容
resultMap标签
resultMap N+1查询
- N+1:先查询出某个表的全部信息,根据这个表的信息
查询另一个表的信息 - 与业务装配的区别:在 service 里面写的代码,由 mybatis 完成装配
实现步骤
1.查询关联对象(1对1)
在 Student 实现类中包含了一个 Teacher 对象
public class Student { private int id; private String name; private int age; private int tid; private Teacher teacher;
在 TeacherMapper 中提供一个查询
<select id="selById" parameterType="int" resultType="wz.pojo.Teacher"> select * from teacher where id=#{0}; </select>
在StudentMapper中
<resultMap id="stuMap" type="wz.pojo.Student"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="age" column="age"/> <result property="tid" column="tid"/> <association property="teacher" select="wz.mapper.TeacherMapper.selById" column="tid"> </association> </resultMap> <select id="selAll" resultMap="stuMap"> select * from student </select>
简化方式
N+1 时,如果列名和属性名相同可以不配置
<resultMap id="stuMap" type="wz.pojo.Student"> <!-- N+1 时,如果列名和属性名相同可以不配置--> <result property="tid" column="tid"/> <association property="teacher" select="wz.mapper.TeacherMapper.selById" column="tid"> </association> </resultMap> <select id="selAll" resultMap="stuMap"> select * from student </select>
2.查询关联对象(1对多)
<resultMap id="mymap" type="wz.pojo.Teacher"> <id column="id" property="id"/> <result column="name" property="name"/> <collection property="list" select="wz.mapper.StudentMapper.selByTid" column="id"/> </resultMap> <select id="selAll" resultMap="mymap"> select * from teacher </select>
<select id="selByTid" resultType="wz.pojo.Student"> select * from student where tid=#{0} </select>
使用实现加载集合数据(联合查询方式)
TeacherMapper
<resultMap id="mymap1" type="wz.pojo.Teacher"> <id column="tid" property="id"/> <result column="tname" property="name"/> <collection property="list" ofType="wz.pojo.Student"> <id column="sid" property="id"/> <result column="sname" property="name"/> <result column="age" property="age"/> <result column="tid" property="tid"/> </collection> </resultMap> <select id="selAll1" resultMap="mymap1"> select t.id tid, t.name tname, s.id sid, s.name sname, age, tid from teacher t left join student s on t.id = s.tid </select>
mybatis 可以通过主键判断对象是否被加载过
Mybatis注解
- 注解:为了简化配置文件
- Mybatis的注解简化mapper.xml文件(涉及动态SQL依然用mapper.xml)
- mapper.xml和注解可以共存
- 使用注解时mybatis.xml中使用
- 查询
@Select("select * from teacher") List<Teacher> selAll();
- 新增
@Insert("insert into teacher values(default,#{name})") int insTeacher(Teacher teacher);
- 修改
@Update("update teacher set name=#{name} where id=#{id}") int updTeacher(Teacher teacher);
- 删除
@Delete("delete from teacher where id=#{0}") int delById(int id);