前言:
Mybatis框架
就是对技术的封装,将基础的技术进行封装,让程序员可以快速的使用,提高开发效率.
java后端框架
vue对js进行封装,ElementUI对css进行封装
mybatis
对jdbc进行封装
正式介绍 mybatis
背景介绍
mybatis原来是apache下面的一个开源项目,名为ibatis,2010年开发团队转移到谷歌 旗下,改名为mybatis.
mybatis介绍
mybatis是一个优秀的数据持久层框架(dao层 数据访问层 数据持久层)
mybatis是对jdbc进行封装,他避免了jdbc中手动设置参数,手动映射结果的操作.
mybatis将jdbc中的接口进行封装,提供了他 自己的类和接口实现.
mybatis可以使用xml配置好注解的方式,将数据库中记录自动映射到java对象中,是一种ORM实现(对象关系映射)将可以自动将数据映射到对象中的这种框架,也称为orm框架
mybatis还提供了动态sql 和 数据缓存 功能
mybatis搭建
1.创建一个Maven项目
2.导入mybatis的jar包(依赖的jar)
3.创建一个全局的mybatis配置文件
配置数据库连接等配置
4.创建数据库,创建表,准备数据
5.创建一个访问接口,定义方法
6.创建接口对应的映射文件,编写sql
7.测试mybatis
//1.mybatis读取配置文件
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
//2.创建SqlSessionFactory, 负责创建SqlSession对象(链接数据库的会话对象,类似collection)
//SqlSessionFactory对象也是只需要创建一个,创建后不需要销毁
SqlSessionFactory SqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
//3.创建SqlSession对象
SqlSession sqlSession = SqlSessionFactory.openSession();
//4.创建接口的代理对象
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
//5.调用
Admin admin = adminDao.findAdminById(1);//让代理对象帮我们调用映射文件中与此接口中相同名称的方法
System.out.println(admin);
//6.关闭调用对象
sqlSession.close();//关闭与数据库的链接对象
搭建补充:
1.在idea中安装mybatisX插件
步骤:点击File-Settings-Plugins-Marketplace搜索MybatisX
2.数据库连接池
链接数据库 每次访问数据库时候,创建一个connection,用完关闭,
但是访问量大了后,每次都要创建新的连接对象,用完关闭,比较耗时.
原理
使用数据库连接池,在池(集合)中事先创建一些链接对象,
用户访问时,就直接在池中获取一个链接对象,用完不销毁,还回到池中,这样就减少频繁创建连接对象
Mybatis-Dao 层面向接口开发
面向接口开发方式只需要程序员编写接口,由Mybatis框架创建接口的动态代理 对象,使用sqlsession.getMapper(接口.class);获得代理对象.
面向接口开发需要遵循以下规范:
1、 Mapper.xml文件中的namespace与mapper接口的类路径相同.
2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同.
3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的 parameterType 的类型相同.
4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的 resultType 的类型相同.
Mybatis 日志
具体选择哪个日志实现由MyBatis的内置日志工厂确定。它会使用最先找到的。 Mybatis 内置的日志工厂提供日志功能,具体的日志实现有以下几种方式: SLF4J|LOG4J|JDK_LOGGINGCOMMONS_LOGGING|STDOUT_LOGGING 配置日志
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
4.封装参数传递:
1.单个参数传递
2.多个参数使用@Param(“id”)绑定
3.返回基本类型
返回简单基本类型
<select id="findAdminInfoCount" resultType="int">
select count(*) from admin
</select>
4.如果传入一个复杂的对象,就需要使用parameterType参数进行类型定义
增删改查 <insert id="唯一标识" useGeneratedKeys="把新增加的主键赋值到自己定义的 keyProperty " keyProperty=“ 接收主键的属性 parameterType="参数类型"> insert into admin(account,password)values(#{account},#{password}) </insert> </mapper> 修改 <update id="唯一标识" parameterType=“参数类型"> update adminsetaccount= #{account},password= #{password} where id= #{id} </update> 删除 <delete id="唯一标识" parameterType="参数类型"> delete from admin where id= #{id} </delete> 查询 <select id="唯一标识" resultType="返回结果集类型"> select * from admin where id= #{id} </select> 结果处理
5.对象映射
如果表中的类名与类中的属性名完全相同,mybatis会自动将查询结果封装
到POJO对象中.
如果java中使用标准驼峰命名,数据库中使用下划线连接命名,可以开始全局
设置实现自动转换
<setting name="mapUnderscoreToCamelCase" value="true"/>
<select id="findUserInfoById"
parameterType="int"resultType="Admin">
select * from admin where id=#{id}
</select>
5.利用集合将多个参数传递
5.数据库事务:
数据库事务:是数据库的一种管理机制,是对一次链接数据库过程的管理 保证一次操作中,执行的多条sql,要么都成功执行,要么都不执行 转账: 1.先从A账户捡钱 sql1 其他代码逻辑(可能出现异常) 2.再向B账户加钱 sql2 提交事务 数据库才会真正的在数据库执行这一次操作的多条sql
sqlSession.commit(); 方法
提交数据库事务,当我们的程序代码没有任何问题时,再向数据库发送提交事务,数据库真正执行我们的sql,出现异常则不提交事务 新增,修改,删除完毕后,我们都需要手动提交事务.
6.单元测试,
程序员使用的测试方式,以方法为单位测试 使用junit组件实现单元测试
@Test 加在方法前
#{} 和 ${}的使用与区别
#{} 是占位符,是采用预编译方式向sql中传值,可以防止sql注入,如果我们往sql中传值,使用#{} sql注入 admin or 1=1
${} 是将内容直接拼接到sql语句中,一般不用于向sql中传值,一般用于向sql中动态传递列名 区别: 底层实现不同
#{} 采用预编译方式,防止sql注入,更加安全
${} 采用字符串拼接,直接将值拼接到sql中 使用场景不同,
#{} 一般用于向sql中的列传值 ${} 一般用于向sql中动态传递列名 例如 排序时 order by 后面的列名可以改变
例如: select 后面的列名也可以自由选择
多表关联查询 resultMap 基本使用:
使用resultMap标签,对查询结果进行自定义映射 type="Admin" 最终返回结果的类型
方式一:直接多表查询
<resultMap id="adminMap" type="Admin"> <id column="adminid" property="id"></id> <result column="account" property="account"></result> </resultMap> <select id="findAdmin" resultMap="adminMap"> select id adminid ,account from admin </select>
<!-- 对关联查询到的学生信息进行自定义被映射封装 --> <resultMap id="studentMap" type="Student"> <id column="id" property="id"></id> <result column="num" property="num"></result> <result column="name" property="name"></result> <result column="gender" property="gender"></result> <!-- 映射关联数据 专业名称 首先会创建一个Major对象然后将专业名称封装到Major对象,最后将Major对象封装到Student对象中 --> <association property="major" javaType="Major"> <result column="mname" property="name"></result> </association> </resultMap> <select id="findStudentById" resultMap="studentMap"> select s.id, s.num, s.name, s.gender, m.name mname from student s inner join major m on s.majorid = m.id where s.id = #{s.id} </select>
方式二:嵌套查询
<!-- 关联查询分割二:嵌套查询 先查询主表(学生表) --> <resultMap id="studentMap1" type="Student"> <id column="id" property="id"></id> <result column="num" property="num"></result> <result column="name" property="name"></result> <result column="gender" property="gender"></result> <!-- 关联表数据 --> <association property="major" javaType="Major" select="findMajorById" column="majorid"></association> </resultMap> <select id="findStudentById1" resultMap="studentMap1"> select id,num,name,gender,majorid from student where id=#{id} </select> <!-- 嵌套查询学生关联专业--> <select id="findMajorById" resultType="Major"> select name from major where id = #{majorid} </select>
<!-- 查询专业时,可以将查询到的多个学生封装到一个集合中 --> <resultMap id="majorMap" type="Major"> <id column="id" property="id"></id> <result column="name" property="name"></result> <!-- 将查询关联到的多条结果封装到集合 --> <collection property="students" javaType="list" ofType="Student"> <result column="num" property="num"></result> <result column="sname" property="name"></result> </collection> </resultMap> <select id="findMajorById" parameterType="int" resultMap="majorMap"> select m.id, s.num, s.name sname, m.name from major m inner join student s on m.id = s.majorid where m.id=#{id} </select> <select id="findMajor" resultMap="majorMap"> select m.id, s.num, s.name sname, m.name from major m left join student s on m.id = s.majorid </select>
关联查询方式二:分两次查 分页操作
<resultMap id="majorMap1" type="Major">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<collection property="students" javaType="list" ofType="Student" select="findStudents" column="id"></collection>
</resultMap>
<select id="findMajors" resultMap="majorMap1">
select id,name from major
</select>
<select id="findStudents" resultType="Student">
select num,name from student where majorid=#{majorid}
</select>
动态sql 数据存储
可以在sql中添加逻辑判断 if test属性条件成立 执行if标签体,不成立就不执行
where标签 当where标签 if语句有条件成立时,就会动态添加where关键字, 还可以删除where后面紧跟着的关键字 例如:or and
<select id="teachers" resultType="com.zhu.mybatispro.model.Teacher">
select * from teacher
<where>
<if test="num!=null">
num=#{num}
</if>
<if test="name!=null">
and name=#{name}
</if>
<if test="gender!=null">
and gender=#{gender}
</if>
</where>
</select>
trim 当条件判断有成立时,可以自定义前缀关键字和后缀关键字 prefix="where" prefixOverrides="and|or"将指定的关键字覆盖
<select id="teachers" resultType="com.zhu.mybatispro.model.Teacher">
select * from teacher
<trim prefix="where" prefixOverrides="and|or">
<if test="num!=null">
num=#{num}
</if>
<if test="name!=null">
and name=#{name}
</if>
<if test="gender!=null">
and gender=#{gender}
</if>
</trim>
</select>
choose标签 中可以加when,otherwise
when 表示条件成立时执行
otherwise 在when条件不成立时,执行语句
<select id="teachers" resultType="com.zhu.mybatispro.model.Teacher">
select * from teacher
<trim prefix="where" prefixOverrides="and|or">
<choose>
<when test="name!=null">
name=#{name}
</when>
<otherwise>
name='李老师'
</otherwise>
</choose>
</trim>
</select>
修改:
<set> set标签
<update id="updateTeacher">
update teacher
<set>
<if test="num!=null">
num=#{num},
</if>
<if test="name!=null">
name=#{name},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</set>
where id=#{id}
</update>
利用trim标签写set标签
<update id="updateTeacher">
update teacher
<trim prefix="set" suffixOverrides=",">
<if test="num!=null">
num=#{num},
</if>
<if test="name!=null">
name=#{name},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</trim>
where id=#{id}
</update>
删除:
foreach是对集合进行遍历,
它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。
它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符
<delete id="deleteTeacher"> delete from teacher where id in <foreach item="id" collection="array" open="(" separator="," close=")"> #{id} </foreach> </delete>
<select id="findTeacher" resultType="com.zhu.mybatispro.model.Teacher">
select
<foreach item="col" collection="list" separator=",">
${col}
</foreach>
from teacher
</select>