目录
2、 创建resources文件夹(存在静态文件的地方),创建项目中MyBatis的核心文件、已经对应操作实例类的文件
2、针对整个实体包(存放所有实体类的包)进行设置,别名为实体类首字母小写的名称 (推荐)
3、Sql映射文件的namespace属性的值必须是对应的Dao
4、Sql映射文件中的Sql 语句的ID编号必须与Dao接口中的方法名相同
一、MyBatis介绍
MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句 本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。 MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的 动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。
(一)、MyBatis主要提供的一些服务
1、封装了JDBC的流程,比如注册驱动、获取con、pre等对象,关闭对象等流程,降低了开发人员使用JDBC的难度;
2、封装了JDBC占位符赋值操作,避免预编译后进行占位符赋值的操作;
3、封装了JDBC中将ResultSet转换成了实体类的操作;
4、提供了Dao代理服务,降低了进行Dao层的开发难度;
(二)、MyBatis框架开发环境搭建
1、将依赖的jar包,引入pom.xml文件中
2、 创建resources文件夹(存在静态文件的地方),创建项目中MyBatis的核心文件、已经对应操作实例类的文件
MyBatis核心文件模板,只需要修改对应的信息
<?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>
<!--
1.设置访问的数据库信息(url,username,password)
2.设置Connection管理方式
3.设置事务管理方式
-->
<!-- 配置 mybatis 环境 -->
<environments default="mysql">
<!--id: 数据源的名称 -->
<environment id="mysql">
<!-- 配置事务类型:使用 JDBC 事务(使用 Connection 的提交和回滚) -->
<transactionManager type="JDBC"/>
<!-- 数据源 dataSource :创建数据库 Connection 对象
type: POOLED 使用数据库的连接池
-->
<dataSource type="POOLED">
<!-- 连接数据库的四个要素 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/s_t"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--设置sql映射文件,在项目中存储位置-->
<mappers>
<mapper resource="student.xml"/>
</mappers>
</configuration>
1)SQL映射文件: 是xml文件。一个SQL映射文件中存储一张表的增删改查语句。
2)mybatis核心配置文件:
提供连接数据库的三要素
提供数据库连接池管理方案
提供SQL映射文件存储位置
实例的操作文件
<?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">
<!--
namespace:必须有值,自定义的唯一字符串
推荐使用:dao 接口的全限定名称
-->
<mapper namespace="com.bjpowernode.dao.StudentDao">
<!--
<select>: 查询数据, 标签中必须是 select 语句
id: sql 语句的自定义名称,推荐使用 dao 接口中方法名称,
使用名称表示要执行的 sql 语句
resultType: 查询语句的返回结果数据类型,使用全限定类名
-->
<!-- <select id="selectStudents" resultType="com.bjpowernode.domain.Student">-->
<!-- <!–要执行的 sql 语句–>-->
<!-- select id,name,email,age from student-->
<!-- </select>-->
<insert id="insertStu">
insert into student(name,age,address) value ('zs',19, 'newYork')
</insert>
<update id="stuUpdate">
update student set age=25, address = 'yellowCity' where name ='zs'
</update>
<delete id="stuDelete">
delete from student where id = '1'
</delete>
</mapper>
3、通过MyBatis操作数据库
直接提交
手动提交
(三)核心类库以及MyBatis内部流程
- SqlSession接口和实现类
- SqlSessionFactory接口和实现类
- SqlSessionFactoryBuilder类
(四)、parameterType属性
1.parameterType属性存在与<insert><update><delete><select>
2.parameterType属性表示当前sql语句中占位符需要的数据类型
3.parameterType属性赋值可以【基本数据类型】,【实体类数据类型】、【Map】
1、基本数据类型
2、实体类数据类型
3、Map数据类型
(五)、resultType属性
1)、resultType,仅仅存在的<select>标签内,定义查询到数据的格式,不能省略; 2)、resultType,既可以是基本数据类型,也可以是实体数据类型; 3)、resultType属性是基本数据类型,说明本次查询只返回一个值 4)、resultType是实体数据类型,此时MyBatis要求将临时表中数据行的内容转换成实例类对象存储, 此时要求临时表的字段名称与实体类的属性名相同,但是可以忽略大小写
(六)、为实体类的全限定名设置一个简短别名
我们实例类的sql映射文件中,使用resultType或者parameterType都需要使用实体类对应的路径,我们给实体类起一个别名后,以后只需要使用别名即可。设置别名需要在MyBatis全局配置文件中,进行设置,有两种方式设置;
1、针对单个实体类设置别名( 不推荐)
<typeAliases>
<!-- 针对与单个实体类起别名,实体类映射文件中直接使用别名。 -->
<typeAlias type="com.zxb.entity.Student" alias="student"/>
</typeAliases>
别名可以起任何名字,最好还是和实体类名称相同,这样容易辨认;
2、针对整个实体包(存放所有实体类的包)进行设置,别名为实体类首字母小写的名称 (推荐)
<typeAliases>
<!--别名是类名首字母小写形式-->
<package name="com.zxb.entity"/>
</typeAliases>
(七)、设置控制台打印日志信息
在MyBatis.xml文件configuration 标签下设置下面标签即可;
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
二、Dao代理服务
(一)、Dao代理服务介绍
1、项目开发中,开发人员只需要开发【Dao】层接口,以及关联的【Sql】即可
2、由MyBatis框架负责在【在内存中创建Dao层接口的实现类】并且负责创建这些【Dao层实现类】的实例化对象
(二)、获取Dao层代理步骤
1、Sql映射文件名称必须和Dao层接口名称完全相同
例如:IStudent、IStudent.xml
2、Sql映射文件必须要和 Dao层接口在同一个文件夹下
3、Sql映射文件的namespace属性的值必须是对应的Dao
4、Sql映射文件中的Sql 语句的ID编号必须与Dao接口中的方法名相同
5、写个测试类测试一下
运行:报错提示没有找到student.xml文件
### The error may exist in student.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource student.xml
原因:因为Maven编译不会将非resoures文件夹下的非java文件进行,从下图可以看出,编译后的classes文件夹下Dao文件夹下没有student.xml文件。
解决办法:在pom文件中添加下面的插件
<!-- 解决maven编译的时候,不将非java文件进行编译 -->
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
添加完了,再次运行测试方法:报错
org.apache.ibatis.binding.BindingException: Type interface com.zxb.Dao.IStudent is not known to the MapperRegistry.
原因:MyBatis框架扫描指定包下所有的Sql文件,MyBatis会找到同一个包下与Sql映射文件同名的接口,并会认为这个接口就是Dao接口,我们需要在MyBatis的配置文件中,告诉 MyBatis那个是Dao接口,如果不指定的话,就会抛出上面的异常;
再次运行,正常,查询出结果了
三、动态SQL服务
(一)、介绍
根据实际传入的数据决定Sql语句组成部分
(二)、动态 SQL 之<if>标签
对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。 语法: sql 语句的部分
(二)、动态 SQL 之<where>
<where>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后 的所有条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL 出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会 严重影响查询效率。
使用标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。需要注意的是,第一个标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错, 系统会将多出的 and 去掉。但其它中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错 。 语法: 其他动态 sql
(三)、动态 SQL 之 <foreach>
<foreach>标签用于实现对于数组与集合的遍历。对其使用,需要注意: ➢ collection 表示要遍历的集合类型, list ,array 等。 ➢ open、close、separator 为对遍历内容的 SQL 拼接。
其余foreach参数等使用见此博客:mybatis总结--动态sql之foreach标签 - Town125 - 博客园
(四)、动态 SQL 之代码片段<include>
<include> 标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用 子标签。该标签可以定义 SQL 语句中的任何部分,所以子标签可以放在动态 SQL 的任何位置。
四、多表查询
(一)、多表查询介绍
数据库表与表之间进行关联很常见,常见有:一对一、一对多、多对一、多对多
一对一:例如:学生表与身份证信息存储表,就是一对一的关系,因为一个人就只有一个身份证,一个身份证号就属于一个人;
一对多:例如:部门表和员工表,一个部门下面有多个员工;
多对一:多对一其实和一对多相反,只要区别看以谁为主表。例如:员工表和部门表,多个员工都是在一个部门下;
多对多:多对多,要依赖第三张表,主要存储两张表直接的关系。例如:学生表和课程表,一个学生可以选择多个课程,一个课程也可以被多个学生选择,这个就是典型的多对多关系;
(二)、mybaits 进行多表查询
1、一对一查询
表:创建一个学生表,一个身份证表
实体类
学生类:可以看出我定义idCardId属性,这个对应我们student表中的idCardId列,我下面又定义一个IdCard类型idCard对象,定义的原因就是通过关联关系查询到IdCard表中的信息,将它存储到idCard对象中
身份证实体类
定义dao层接口
Sql映射文件
我们发现,select标签中 需要添加一个resultMap属性,resultMap属性表示你可以自定义查询数据的映射关系;
<resultMap属性> id:表示查询数据映射关系的唯一标识 type: 表示主表的实体类
<result> column:表示查询语句,查询的数据列名称; property: 表示对应实体类的属性名称
<association> 一对一,多对一时候使用。 property: 表示对应实体类的属性名称 javaType:表示对应属性的类型
测试类
2、一对多
表:学生表 和 部门表 (一个部门下面有多个学生)
实体类
部门类
因为一个部门下可能有多个学生,因此我们需要定一个List属性,来接收查到的所有学生信息;
学生类
dao层服务
Sql映射文件
<collection>一对多、多对多,类型是集合使用。property属性名称,ofType list里面存储对象的数据类型
测试类
3、多对一
表:学生表 和 部门表
实体类
学生实体
我们可以理解,一个学生只会属于一个部门,其实多对一和一对一是一样的;
部门实体类
Sql映射文件
测试类
4、多对多
表:学生表 和 课程表 和中间表(存储学生和课程之间的关系)
实体类
学生实体类
一个学生可能选择多个课程,因此需要通过List接收每个课程对象,由此可以看出,多对多和一对多一样;
课程实体类
Sql映射文件
可以发现我们查出了课程的id和name并且给它们两个起了别名,我们为什么要起别名呢?
如果不起别名会有什么效果呢?
因为courses表中列名称也是id和name, student表列名称也有id和name,我们在ResultMap里面定义student的id和name的映射关系,在collection里面定义courses表的映射关系,如果我们定义的时候没有使用别名,依然使用id映射id,name映射name,mybatis查询到数据后,会将courses表的中id和name覆盖成student表的id和name
我们发现就是出现了覆盖,我们本来查询课程id和课程名称,但是被学生id和name给覆盖
下面使用别名可以解决上面的问题
测试类