一、MyBatis概述
1.1、MyBatis概念
MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发。
持久层:负责将数据到保存到数据库的那一层代码。
JavaEE三层架构:表现层、业务层、持久层。以后开发我们会将操作数据库的Java代码作为持久层。而Mybatis就是对jdbc代码进行了封装。
框架:就是一个半成品软件,用来解决一类问题的一套可重用的、通用的、软件基础代码模型,在框架的基础之上构建软件编写更加高效、规范、通用、可扩展。
如下图所示有一个石膏娃娃,这个就是一个半成品。你可以在这个半成品的基础上进行不同颜色的涂鸦形成不同的产品。
1.2、JDBC的缺点
硬编码:
注册驱动、获取连接的代码有很多字符串,而这些是连接数据库的四个基本信息,以后如果要将Mysql数据库换成其他的关系型数据库的话,这四个地方都需要修改,如果放在此处就意味着要修改我们的源代码。
SQL语句代码如果表结构发生变化,SQL语句就要进行更改。这也不方便后期的维护。
操作繁琐:
手动设置参数
而使用MyBatis,硬编码可以配置到配置文件;操作繁琐的地方mybatis都可以自动完成。
二、MyBatis快速入门
![](https://img-blog.csdnimg.cn/direct/bc7f83a5d79048b589f940dec5b95dd1.png)
1.创建数据表
create database mybatis;
use mybatis;
drop table if exists tb_user;
create table tb_user(
id int primary key auto_increment,
username varchar(20),
password varchar(20),
gender char(1),
addr varchar(30)
);
INSERTINTO tb_user VALUES(1,'zhangsan','123','男','北京');
INSERTINTO tb_user VALUES(2,'李四','234','女','天津');
INSERTINTO tb_user VALUES(3,'王五','11','男','西安');
2.建立模型类,用于数据库数据的映射
public class User{
private int id;
private String username;
private String password;
private String gender;
private String addr;
//省略了setter和getter
}
3.pom.xml 配置文件中添加依赖的坐标
<dependencies>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<!--添加slf4j日志api-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!--添加logback-classic依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!--添加logback-core依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
注意需要在项目的 resources 目录下创建logback的配置文件(略)
4.编写 SQL 映射文件 --> 统一管理sql语句,解决硬编码问题
在模块下的 resources 目录下创建配置文件UserMapper.xml内容如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC"-//mybatis.org//DTDMapper3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
<select id="selectAll" resultType="com.itheima.pojo.User">
select * from tb_user;
</select>
</mapper>
5.编写 MyBatis 核心配置文件 -- > 替换连接信息解决硬编码问题
在模块下的 resources 目录下创建mybatis的配置文件mybatis-config.xml内容如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC"-//mybatis.org//DTDConfig3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--别名,用来简化映射配置文件中属性值的编写-->
<typeAliases>
<typeAlias alias="User" type="com.example.domain.User"/>
<!-- 包扫描方式,自动注册该包下所有类的别名 -->
<!--MyBatis会自动为指定包下的所有类注册别名,别名默认为类名-->
<package name="com.itheima.pojo"/>
</typeAliases>
<!--environments:配置数据库连接环境信息。可以配置多个environment,
通过default属性切换不同的environment-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatisuseSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载sql映射文件-->
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
6.编写 MybatisDemo 测试类
public class MyBatisDemo{
public static void main(String[] args) throws IOException{
//1.加载mybatis的核心配置文件,获取SqlSessionFactory
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=
new SqlSessionFactoryBuilder().build(inputStream);
//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession=sqlSessionFactory.openSession();
//3.执行sql
List<User> users=sqlSession.selectList("test.selectAll");
//参数是一个字符串,该字符串必须是映射配置文件的namespace.id
System.out.println(users);
//4.释放资源
sqlSession.close();
}
}
在入门案例映射配置文件中若存在报红的情况。问题如下:
产生的原因:Idea和数据库没有建立连接,不识别表信息。但它并不影响程序的执行。
解决方式:在Idea中配置MySQL数据库连接。
三、Mapper代理开发
3.1、Mapper代理开发概述
之前我们写的代码是基本使用方式,它也存在硬编码的问题,如下:
这里调用selectList()方法传递的参数是映射配置文件中的 namespace.id值。这样写也不便于后期的维护。如果使用Mapper 代理方式(如下图)则不存在硬编码问题。
Mapper 代理方式的目的:解决原生方式中的硬编码;简化后期执行SQL。
![](https://img-blog.csdnimg.cn/direct/b9a1a57246e34bd48af8fe3a8e36880d.png)
3.2、使用Mapper代理要求
使用Mapper代理方式,必须满足以下要求:
1.定义与SQL映射文件同名的Mapper接口,并将Mapper接口和SQL映射文件放置在同一目录
2.设置SQL映射文件的namespace属性为Mapper接口全限定名
3.在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
3.3、代码实现
1.在com.itheima.mapper包下创建 UserMapper接口,代码如下:
public interface UserMapper{
List<User> selectAll();
User selectById(int id);
}
<!--
namespace:名称空间。必须是对应接口的全限定名
-->
<mapper namespace="com.itheima.mapper.UserMapper">
<select id="selectAll" resultType="com.itheima.pojo.User">
select * from tb_user;
</select>
</mapper>
public class MyBatisDemo2{
public static void main(String[] args)throws IOException{
//1.加载mybatis的核心配置文件,获取SqlSessionFactory
Stringresource="mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactorysqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.执行sql
//3.1获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAll();
System.out.println(users);
//4.释放资源
sqlSession.close();
}
}
<mappers>
<!--加载sql映射文件-->
<mapperresource="UserMapper.xml"/>
</mappers>
改为:
<mappers>
<!--加载sql映射文件-->
<!--<mapper resource="com/itheima/mapper/UserMapper.xml"/>--> <!--Mapper代理方式-->
<packagename="com.itheima.mapper"/>
</mappers>
四、MyBatis案例练习
4.1 配置文件实现CURD
环境准备:
1.数据库表(tb_brand)及数据准备
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand (
-- id 主键
id int primary key auto_increment,
-- 品牌名称
brand_name varchar(20),
-- 企业名称
company_name varchar(20),
-- 排序字段
ordered int,
-- 描述信息
description varchar(100),
-- 状态:0:禁用 1:启用
status int
);
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1);
2.创建实体类
public class Brand {
// id 主键
private Integer id;
// 品牌名称
private String brandName;
// 企业名称
private String companyName;
// 排序字段
private Integer ordered;
// 描述信息
private String description;
// 状态:0:禁用 1:启用
private Integer status;
//省略 setter and getter。自己补全这部分代码
}
安装MyBatisX插件:可以自动生成对应接口方法的映射文件statement
3.编写接口方法
public interface BrandMapper {
/*** 查询所有 */
List<Brand> selectAll();
}
4. 创建名 BrandMapper.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.itheima.mapper.BrandMapper">
<!--statement-->
<select id="selectAll" resultType="brand">
select * from tb_brand;
</select>
</mapper>
5.创建核心配置文件mybatis-config.xml(略)
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC"-//mybatis.org//DTDConfig3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.itheima.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper namespace="com.itheima.mapper.BrandMapper"></package>
</mappers>
</configuration>
6.编写测试方法
@Test
public void testSelectAll() throws IOException {
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
List<Brand> brands = brandMapper.selectAll();
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
}
如图,运行以上程序发现brandName,companyName是空值没有封装成功,为什么?
因为数据库表字段 和 实体类的属性名称不一样,则不能自动封装数据,解决方法:
1.起别名:不一样的列名起别名,让别名和实体类属性名一样(每个查询都要写一次,麻烦)
<select id="selectAll" resultType="brand">
select id, brand_name as brandName, company_name as companyName,
ordered, description, status from tb_brand;
</select>
2.sql片段(不灵活)
<sql id="brand_column">
id, brand_name as brandName, company_name as companyName, ordered,
description, status
</sql>
<select id="selectAll" resultType="brand">
select <include refid="brand_column" /> from tb_brand;
</select>
3.resultMap
<resultMap id="brandResultMap" type="brand">
<!--id:完成主键字段的映射 column:表的列名
property:实体类的属性名 result:完成一般字段的映射
-->
<result column="brand_name" property="brandName"/>
<result column="company_name" property="companyName"/>
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select * from tb_brand;
</select>
注意:在上面只需要定义 字段名 和 属性名 不一样的映射,而一样的则不需要专门定义出来。
4.1.1 查询详情
1.在 BrandMapper 接口中定义根据id查询数据的方法
/*** 查看详情:根据Id查询 */
Brand selectById(int id);
2.在映射配置文件中编写 statement ,使用 resultMap
<select id="selectById" resultMap="brandResultMap">
select * from tb_brand where id = #{id};
</select>
3.测试方法中添加
//接收参数,该id以后需要传递过来
int id = 1;
// 执行方法
Brand brand = brandMapper.selectById(id);
4.运行程序
(1)parameterType使用
对于有参数的mapper接口方法,我们在映射配置文件中应该配置 ParameterType 来指定参数类型。
只不过该属性都可以省略。
<select id="selectById" parameterType="int" resultMap="brandResultMap">
select * from tb_brand where id = ${id};
</select>
(2)SQL语句中特殊字段处理
以后肯定会在SQL语句中写一下特殊字符,比如某一个字段大于某个值
> < 等这些字符在xml中有特殊含义,所以此时我们需要将这些符号进行转义
<select id="selectById" parameterType="int" resultMap="brandResultMap">
select * from tb_brand where id < #{id};
</select>
控制台显示的SQL语句,能看到使用?进行占位说明我们在映射配置文件中的写的 #{id} 最终会被?进行占位。
mybatis提供了两种参数占位符:(JDBC中PreparedStatement)
#{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是PreparedStatement(开发中使用此占位符)
${} :拼接SQL。底层使用的是 Statement ,会存在SQL注入问题。
4.1.2 多条件查询
1.在 BrandMapper 接口中定义多条件查询的方法
方法一:使用 @Param("参数名称") 标记每一个参数,
在映射配置文件中就需要使用 #{参数名称} 进行占位
List<Brand> selectByCondition(@Param("status") int status, @Param("companyName")
String companyName,@Param("brandName") String brandName);
方法二:将多个参数封装成一个实体对象 ,将该实体对象作为接口的方法参数。
该方式要求在映射配置文件的SQL中使用 #{内 容} 时,里面的内容必须和实体类属性名保持一致。
List<Brand> selectByCondition(Brand brand);
方法三:将多个参数封装到map集合中,将map集合作为接口的方法参数。
该方式要求在映射配置文件的SQL中使用 #{内容}时,里面的内容必须和map集合中键的名称一致。
List<Brand> selectByCondition(Map map);
2.编写SQL语句
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
where status = #{status}
and company_name like #{companyName}
and brand_name like #{brandName}
</select>
3.编写测试方法
@Test
public void testSelectByCondition() throws IOException {
//接收参数 int status = 1;
String companyName = "华为";
String brandName = "华为";
// 处理参数
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
//方式一 :接口方法参数使用 @Param 方式调用的方法
//List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
//方式二 :接口方法参数是 实体类对象 方式调用的方法
//封装对象
/* Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);*/
//List<Brand> brands = brandMapper.selectByCondition(brand);
//方式三 :接口方法参数是 map集合对象 方式调用的方法
Map map = new HashMap();
map.put("status" , status);
map.put("companyName", companyName);
map.put("brandName" , brandName);
List<Brand> brands = brandMapper.selectByCondition(map);
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
4.1.3 动态多条件查询
上述功能实现存在很大的问题。用户在输入条件时,肯定不会所有的条件都填写。如果条件没有填完整程序运行会出问题。我们需要灵活的输入条件查询。针对上述的需要,Mybatis对动态SQL有很强大的支撑:
//test 属性:逻辑表达式;if 标签:条件判断
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
<where>
<if test="status != null">
and status = #{status}
</if>
<if test="companyName != null and companyName != '' ">
and company_name like #{companyName}
</if>
<if test="brandName != null and brandName != '' ">
and brand_name like #{brandName}
</if>
</where>
</select>
这种SQL语句就会根据传递的参数值进行动态的拼接。哪个属性有值那么就会值拼接哪个条件。
4.1.4 单个条件动态查询
如上图所示,在查询时只能选择 品牌名称 、 当前状态 、 企业名称 这三个条件中的一个,但是用户到底选择哪儿一个,我们并不能确定。这种就属于单个条件的动态SQL语句。
1.编写接口方法
/**
* 单条件动态查询
* @param brand
* @return
*/
List<Brand> selectByConditionSingle(Brand brand);
2.映射配置文件中编写 statement
<select id="selectByConditionSingle" resultMap="brandResultMap">
select *
from tb_brand
<where>
<choose><!--相当于switch-->
<when test="status != null"><!--相当于case-->
status = #{status}
</when>
<when test="companyName != null and companyName != '' "><!--相当于case-->
company_name like #{companyName}
</when>
<when test="brandName != null and brandName != ''"><!--相当于case-->
brand_name like #{brandName}
</when>
</choose>
</where>
</select>
3.编写测试方法
@Test
public void testSelectByCondition() throws IOException {
//接收参数 int status = 1;
String companyName = "华为";
String brandName = "华为";
// 处理参数
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
//封装对象
Brand brand = new Brand();
//brand.setStatus(status);
brand.setCompanyName(companyName);
//brand.setBrandName(brandName);
List<Brand> brands = brandMapper.selectByCondition(brand);
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
4.1.5 添加数据
1.添加接口方法
void add(Brand brand);
2.映射配置文件中编写添加数据的 statement
<insert id="add">
insert into tb_brand (brand_name, company_name, ordered, description, status)
values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
3.编写测试方法(多条件查询改一下)
//接收参数
int status = 1;
String companyName = "波导手机"; S
tring brandName = "波导";
String description = "手机中的战斗机";
int ordered = 100;
//4. 执行方法
brandMapper.add(brand);
Integer id = brand.getId();
System.out.println(id);//打印出null,无法获取主键id
//提交事务
sqlSession.commit();
添加-主键返回:在数据添加成功后,获取插入数据库数据的主键(主键是自增长)。
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into tb_brand (brand_name, company_name, ordered, description, status)
values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
在 insert 标签上添加如下属性:
useGeneratedKeys:是够获取自动增长的主键值。true表示获取
keyProperty :指定将获取到的主键值封装到哪儿个属性里
此时再在测试方法里面打印获取主键id,可以打印出来
brandMapper.add(brand);
Integer id = brand.getId();
System.out.println(id);
4.1.6 修改数据
1.在 BrandMapper 接口中定义修改方法。
void update(Brand brand);
2.在 BrandMapper.xml 映射配置文件中添加修改数据的 statement 。
//set 标签可以用于动态包含需要更新的列,忽略其它不更新的列。
<update id="update">
update tb_brand
<set>
<if test="brandName != null and brandName != ''">
brand_name = #{brandName},
</if>
<if test="companyName != null and companyName != ''">
company_name = #{companyName},
</if>
<if test="ordered != null">
ordered = #{ordered},
</if>
<if test="description != null and description != ''">
description = #{description},
</if>
<if test="status != null">
status = #{status}
</if>
</set>
where id = #{id};
</update>
3.编写测试方法
//接收参数
int status = 0;
String companyName = "波导手机";
String brandName = "波导";
String description = "波导手机,手机中的战斗机";
int ordered = 200;
int id = 6;
Brand brand = new Brand();
brand.setStatus(status);
brand.setId(id);
int count = brandMapper.update(brand);
System.out.println(count);
//提交事务
sqlSession.commit();
4.1.7 删除一行数据
1.在 BrandMapper 接口中定义根据id删除方法。
void deleteById(int id);
2.在 BrandMapper.xml 映射配置文件中编写删除一行数据的 statement
<delete id="deleteById">
delete from tb_brand where id = #{id};
</delete>
3.编写测试方法
int id = 6;
// 执行方法
brandMapper.deleteById(id);
//提交事务
sqlSession.commit();
4.1.8 批量删除
1.在 BrandMapper 接口中定义删除多行数据的方法。
void deleteByIds(int[] ids);
2.在 BrandMapper.xml 映射配置文件中编写删除多条数据的 statement 。
//foreach 标签:用来迭代任何可迭代的对象
<delete id="deleteByIds">
delete from tb_brand where id
in
<foreach collection="array" item="id" separator="," open="(" close=")">
#{id}
</foreach>
;
</delete>
collection 属性:mybatis会将数组参数,封装为一个Map集合。
item 属性:本次迭代获取到的元素。
separator 属性:集合项迭代之间的分隔符。
foreach 标签不会错误地添加多余的分隔符;也就是最后一次迭代不会加分隔符
open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次
lose 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次
3.编写测试方法
//接收参数
int[] ids = {5,7,8};
//执行方法
brandMapper.deleteByIds(ids);
4.2 MyBatis参数封装
User select(@Param("username") String username,@Param("password") String password);
<select id="select" resultType="user">
select * from tb_user
where username=#{username}
and password=#{password}
</select>
我们在接口方法中定义多个参数,Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,
而键在没有使用 @Param注解时有以下命名规则:
以 arg 开头 :第一个参数就叫 arg0,第二个参数就叫 arg1,以此类推。如:
map.put("arg0",参数值1);
map.put("arg1",参数值2);
以 param 开头 : 第一个参数就叫 param1,第二个参数就叫 param2,依次类推。如:
map.put("param1",参数值1);
map.put("param2",参数值2);
User select(String username,String password);
<select id="select" resultType="user">
select * from tb_user
where username=#{arg0}
and password=#{arg1}
</select>
或
<select id="select" resultType="user">
select * from tb_user
where username=#{param1}
and password=#{param2}
</select>
User select(@Param("username") String username, String password);
Mybatis 在封装 Map 集合时,键名就会变成如下:(agr0被替代了)
map.put("username",参数值1);
map.put("arg1",参数值2);
map.put("param1",参数值1);
map.put("param2",参数值2);
结论:以后接口参数是多个时,在每个参数上都使用 @Param 注解。这样代码的可读性更高。
4.3 注解实现CURD
注解是用来替换映射配置文件方式配置的,所以使用了注解,就不需要再映射配置文件中书写对应的 statement;注解完成简单功能,配置文件完成复杂功能。
1.创建数据库表
create database spring_db character set utf8;
use spring_db;
create table tbl_account(
id int primary key auto_increment,
name varchar(35),
money double
);
2.导入pom.xml相关依赖(略)
3.根据表创建模型类
public class Account implements Serializable {
private Integer id;
private String name;
private Double money;
//setter...getter...toString...方法略
}
4.创建Dao接口(Mybatis注解方式)
public interface AccountDao {
@Insert("insert into tbl_account(name,money)values(#{name},#{money})")
void save(Account account);
@Delete("delete from tbl_account where id = #{id} ")
void delete(Integer id);
@Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ")
void update(Account account);
@Select("select * from tbl_account")
List<Account> findAll();
@Select("select * from tbl_account where id = #{id} ")
Account findById(Integer id);
}
5.创建Service接口和实现类
public interface AccountService {
void save(Account account);
void delete(Integer id);
void update(Account account);
List<Account> findAll();
Account findById(Integer id);
}
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
public void save(Account account) {
accountDao.save(account);
}
public void update(Account account){
accountDao.update(account);
}
public void delete(Integer id) {
accountDao.delete(id);
}
public Account findById(Integer id) {
return accountDao.findById(id);
}
public List<Account> findAll() {
return accountDao.findAll();
}
}
6.添加jdbc.properties文件:resources目录下添加,用于配置数据库连接四要素
//useSSL:关闭MySQL的SSL连接
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false
jdbc.username=root
jdbc.password=root
7.添加Mybatis核心配置文件
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC"-//mybatis.org//DTDConfig3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--读取外部properties配置文件-->
<properties resource="jdbc.properties"></properties>
<typeAliases>
<!-- 包扫描方式,自动注册该包下所有类的别名 -->
<!--MyBatis会自动为指定包下的所有类注册别名,别名默认为类名-->
<package name="com.itheima.domain"/>
</typeAliases>
<!--数据源-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!--映射文件扫描包路径-->
<mappers>
<package name="com.itheima.dao"></package>
</mappers>
</configuration>
8.编写应用程序
public class App {
public static void main(String[] args) throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder =
new SqlSessionFactoryBuilder();
// 2. 加载SqlMapConfig.xml配置文件(核心配置文件)
InputStream inputStream =
Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory =
sqlSessionFactoryBuilder.build(inputStream);
// 4. 获取SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行查询,获取结果User
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
Account ac = accountDao.findById(1);
System.out.println(ac);
// 6. 释放资源
sqlSession.close();
}
}
9.运行程序
Account{id=1, name='Tom',money=1000.0}