一、了解mybatis框架
MyBatis是一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis可以通过简单的 XML或注解来配置和映射原始类型、接口和Java POJO(Plain Old Java Objects,普通老式Java 对象)为数据库中的记录
二、mybatis与其它方式相比
Mybatis是对JDBC轻量级的封装
性能:JDBC>Mybatis>Hibernate
Mybatis:半自动框架,自定义sql
Hibernate:全自动的,全靠配置文件,一般都是全字段,配置映射关系
功能:Hibernate>Mybatis>JDBC
多表联查,sql不好些,字段多一些
只需要配置关系就行了,不需要写sql、ssh
三、项目中所需要的jar包
1.单元测试
XML
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
2.mybatis的核心包
XML
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
3.mysql的驱动
XML
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.2.0</version>
</dependency>
4.日志
XML
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
四、创建工程的步骤
1.创建maven工程
2.导入所需要的jar包
3.创建核心配置文件mybatis-config.xml、xxxMapper.xml
mybatis-config.xml
XML
<?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="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--配置mybatis的映射文件-->
<mappers>
<mapper resource="com/zx/dao/UserMapper.xml"></mapper>
</mappers>
</configuration>
注意:一旦mybatis和Spring整合,environments则不需要再单独提供
xxxMapper.xml
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="com.zx.dao.UserDao">
<insert id="addUser" parameterType="com.zx.entity.User">
insert into t_user values (null,#{username},#{password})
</insert>
</mapper>
注意:<mapper>中可以添加增删改查的功能
注意事项:
1.mybatis核心配置文件mybatis-config.xml或者xxxMapper.xml
2.核心配置文件中需要写入两部分内容:数据库环境配置和映射文件
3.映射文件的名称XXXMapper.xml或者XXXDao.xml
4.映射文件的路径应该在资源文件夹resources下和XXXDao相同文件夹下
5.映射文件中的mapper中的命名空间namespace必须写XXXDao的全限定类名<mapper namespace="XXXDao的全类名">
6.映射文件中的标签id名字必须是XXXDao接口中方法的名称
4.mybatis的访问过程及原理
(1)访问过程
通过输入流读取mybatis-config.xml文件:
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
通过配置文件创建SqlSessionFactory:
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
通过sqlSessionFactory创建核心类sqlSession:
SqlSession sqlSession = sqlSessionFactory.openSession();
通过sqlSession获取dao接口:
UserMapper userDao = sqlSession.getMapper(UserMapper.class);
(2)访问原理
通过输入流读取到的mybatis-config.xml文件获取SqlSessionFactory
通过sqlSessionFactory创建核心类sqlSession
创建数据库操作对象Connection
mybatis在运行过程中通过动态代理模式创建xxxDao的子实现类
通过对象调用方法,找到命名空间并执行sql语句
利用反射技术,将实体类中的属性和sql语句中的字段一一对应
5.mybatis进行增删改查操作
(1)XML版本
增
XML
<insert id="addUser" parameterType="com.xszx.beans.User">
insert into user values (null,#{name},#{password})
</insert>
删
XML
<delete id="deleteUser" parameterType="com.xszx.beans.User">
delete from user where id=#{id}
</delete>
改
XML
<update id="updateUser" parameterType="com.xszx.beans.User">
update user set name=#{name},password=#{password} where id=#{id}
</update>
查
XML
<select id="getUser" resultType="com.xszx.beans.User">
select * from user
</select>
(2)注解版本
java
@Insert("insert into user values (null,#{name},#{password})")
void addUser(User user);
@Select("select * from user where id=#{id}")
User getUsers(User user);
@Select("select * from user")
List<User> getUser(User user);
@Update("update user set name=#{name},password=#{password} where id=#{id}")
void updateUser(User user);
@Delete("delete from user where id=#{id}")
void deleteUser(User user);
注意:使用注解版本时,需要修改mybatis-config.xml文件
6.参数问题
(1)如果方法中参数是自定义对象类型,那么#{}中的属性必须是实体类中的属性
(2)如果方法中的参数是其他类型,那么#{}中的属性不一定是实体类中的属性
(3)如果方法中的参数是其他类型,并且有多个参数
解决方式:
方式一:在抽象方法的形式参数前面添加注解:@Param("参数名字")
方式二:以param1、param2、......来替换(不推荐)
方式三:以map集合添加多个参数,#{}中填写mao中key的值
7.返回值问题
(1)返回值为单个属性
在xml文件中,通过resultType属性来设置返回值的类型
(2)返回值为多个属性
方式一:采用对象形式
将返回值放入对象当中
方式二:采用map形式
将返回值以键值对的形式放入map当中
注意:
1.返回map的时候,键是属性名称,值就是具体的值,只能返回一条数据,返回多条就会报错
2.resultType一般都是返回已有的类型,或者你写好的实体类型,可以直接对应的类型
若是字段或者类型,或者不是能很好的直接对应,就需要用药自定义对应的类型
8.关联映射
(1)多对一
resultMap 如果返回值中有其他对象的属性时使用
属性:
id:固定id
type:查询结果的返回类型
子标签:
id:表中的主键
column:数据表中的列名称
property:实体类中的属性
result:其他属性
column:数据表中的列名称
property:实体类中的属性
方式一:发送多次sql语句,每张表进行单独查询,通过select属性向对方映射文件中进行查询
association: 关联标签 出现在"多"方
column:数据表中的列名称
property:实体类中的属性
select: 需要指定命名空间.id去查询关联对象
javaType: 查询结束之后的返回类型
XML
<select id="getUser04" parameterType="int" resultMap="userResult">
select * from t_user where id = #{id}
</select>
<resultMap id="userResult" type="com.zx.entity.User">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="age" property="age"></result>
<association column="gid" property="group" select="com.zx.dao.GroupDao.getGroupByid" javaType="com.zx.entity.Group"></association>
</resultMap>
这个方法需要注意,select放的是你要二次执行的接口,(简单来说就是一个完整的查询接口,需要有mapper,有xml),查询的内容通常是用了关联字段或外键,没有中间表,但是查询完成以后,还是可以显示关联字段的所有信息。若是没有关联字段,任然需要联查
方式二:发送一次sql语句,进行联表查询,需要注意SQL语句的性能,不需要使用select属性
association: 关联标签 出现在"多"方
column:数据表中的列名称
property:实体类中的属性
javaType: 查询结束之后的返回类型
association打开,可以嵌入子标签:
id:对方表中的主键
column:数据表中的列名称
property:实体类中的属性
result:其他属性
column:数据表中的列名称
property:实体类中的属性
XML
<select id="getUser05" parameterType="int" resultMap="userResult05">
select u.id uid,u.username username,u.password password,u.age age,g.id gid,g.gname
gname from t_user u,t_group g where u.gid = g.id and u.id = #{id};
</select>
<resultMap id="userResult05" type="com.zx.entity.User">
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="age" property="age"></result>
<association column="gid" property="group" javaType="com.zx.entity.Group">
<id column="gid" property="id"></id>
<result column="gname" property="gname"></result>
</association>
</resultMap>
(2)一对多
resultMap:如果返回值中有其他对象的属性时使用
属性:
id:固定id
type:查询结果的返回类型
子标签:
id:表中的主键
column:数据表中的列名称
property:实体类中的属性
result:其他属性
column:数据表中的列名称
property:实体类中的属性
collection: 集合映射标签 出现在"一"方
column:数据表中的列名称
property:实体类中的属性
select: 需要指定命名空间.id去查询关联对象
ofType: 查询结束之后的返回类型
方式一:发送多次sql语句,每张表进行单独查询,通过select属性向对方映射文件中进行查询
XML
<select id="getGroupByid02" resultMap="groupResult02" parameterType="int">
select * from t_group where id = #{id}
</select>
<resultMap id="groupResult02" type="com.zx.entity.Group">
<id column="id" property="id"></id>
<result column="gname" property="gname"></result>
<collection column="id" property="users" select="com.zx.dao.UserDao.getUsersByGid" ofType="com.zx.entity.User"></collection>
</resultMap>
对象对应多个用户用list展示
方式二:发送一次sql语句,进行联表查询,需要注意SQL语句的性能,不需要使用select属性
collection打开,可以嵌入子标签:
id:对方表中的主键
column:数据表中的列名称
property:实体类中的属性
result:其他属性
column:数据表中的列名称
property:实体类中的属性
XML
<select id="getGroupByid03" resultMap="groupResult03" parameterType="int">
select g.id gid,g.gname gname,u.id uid,u.username username,u.password password,u.age
age from t_user u,t_group g where u.gid = g.id and g.id = #{gid}
</select>
<resultMap id="groupResult03" type="com.zx.entity.Group">
<id column="gid" property="id"></id>
<result column="gname" property="gname"></result>
<collection column="gid" property="users" ofType="com.zx.entity.User" >
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="age" property="age"></result>
</collection>
</resultMap>
9.动态sql
(1)if标签
条件判断
XML
<if test=""><!--test是条件-->
<!--满足条件执行的语句-->
</if>
(2)where标签
替换where关键字,会动态的去掉第一个条件前的 and,如果所有的参数没有值则不加where关键字(通常和if标签使用)
XML
<where>
<if test=""><!--test是条件-->
<!--满足条件执行的语句-->
</if>
</where>
(3)choose标签
相当于java的switch语句
when标签:用于定义条件成立时执行的代码块,它包含一个 test 属性,用于指定该条件分支的判断条件
otherwise标签:用于定义默认的代码块,当所有的 <when> 条件都不成立时,将行 <otherwise> 中定义的代码块
XML
<choose>
<when test=""><!--test是条件-->
<!--满足条件执行的语句-->
</when>
<otherwise>
<!--全部when不满足则执行是语句-->
</otherwise>
</choose>