持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
MyBatis快速入门
- MyBatis是一款优秀的持久层框架,用于简化JDBC开发
- MyBatis 本是 Apache的一个开源项目iBatis, 2010年这个项目由apache softwarefoundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github
- 官网: mybatis.org/mybatis-3/z…
持久层
- 负责将数据到保存到数据库的那一层代码
- JavaEE三层架构:表现层,业务层,持久层
框架
- 框架就是一个半成品软件,是一套可重用的,通用的,软件基础代码模型
- 在框架的基础之上构建软件编写更加高效,规范,通用,可扩展
JDBC的缺点:
1.硬编码:注册驱动,获取连接。 SQL语句
2.操作繁琐:手动设置参数。 手动封装结果集
因此,MyBatis就是用来解决JDBC的缺点的
具体流程:
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)
);
INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');
2.在pom.xml中加入如下代码
<dependency>
<!--mybatis 依赖 -->
<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.32</version>
</dependency>
3.创建一个mybatis-config.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"/>
<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>
</environments>
<mappers>
<!--加载sql映射文件-->
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
4.创建一个UserMapper.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">
<!--
namespace:名称空间
-->
<mapper namespace="test">
<select id="selectAll" resultType="xiaokasidi.User">
select * from tb_user;
</select>
</mapper>
5.编码
//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");
System.out.println(users);
//4.关闭资源
sqlSession.close();
mysql8.0后要记得在下图第二行中加入serverTimezone=GMT
Mapper代理开发
1.定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下。
注意:在resource文件夹下,创建新文件夹并且命名时,要用/不能用.
2.设置SQL映射文件的namespace属性为Mapper接口全限定名
在UserMapper.xml文件下
3.在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
4.编码
1.通过SqlSession的getMapper方法获取Mapper接口的代理对象
2.调用对应方法完成sql的执行
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
List<User> users = usermapper.selectAll();
System.out.println(users);
配置文件完成增删改查
环境准备:
查询:1.查询所有数据
在进行查询前,最好都进行如上的分析
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 branmapper = sqlSession.getMapper(BrandMapper.class);
//4.执行方法
List<Brand> brands = branmapper.selectAll();
System.out.println(brands);
//5.释放资源
sqlSession.close();
bug1:运行时,出了个BindingException的bug
原因:没在config.xml文件中加入
bug2:报mybatis.tb_brand错误。
原因:数据库表名错了
数据库表的字段名称和实体类的属性名称不一样,则不能自动封装数据
1.起别名:对不一样的的列名起别名,让别名和实体类的属性名一样 缺点:每次查询都要定义一次别名
<select id="selectAll" resultType="xiaokasidi.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="xiaokasidi.Brand">
select <include refid="brand_column"></include>
from tb_brand;
</select>
3.resultMap
1.定义resultMap标签
2.在select使用resultMap属性替换resultType属性
id:唯一标识
type:映射的类型,支持别名
-->
<resultMap id="brandResult" type="xiaokasidi.Brand">
<!--
id:完成主键字段的映射
column:表的列名
property:实体类的属性名
result:完成一般字段的映射
column:表的列名
property:实体类的属性名
-->
<result column="brand_name" property="brandName"></result>
<result column="company_name" property="companyName"></result>
</resultMap>
<select id="selectAll" resultMap="brandResult">
select *
from tb_brand;
</select>
2.查看详情
、
参数占位符:
1.#{}:会将其替换为?,为了防止sql注入
2.${}:拼sql。会存在sql注入问题
3.使用时机:
*参数传递的时候:#{}
*表名或者列名不固定的情况下:${}会存在sql注入问题
参数类型:parameterType:可以省略
特殊字符处理:
1.转义字符:例:< -> <
2.CDATA区:<![CDATA[
<
]]>
-->
<select id="selectById" parameterType="int" resultMap="brandResult">
select *
from tb_brand where id = #{id};
</select>
3.条件查询
多条件查询
有三种不同的参数
public void testSelectByCondition() throws IOException {
//接收参数
int status = 1;
String companyName = "华为";
String brandName = "华为";
//处理参数 1.散装参数 2.对象参数
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//封装对象 2.对象参数
// Brand brand = new Brand();
// brand.setStatus(status);
// brand.setCompanyName(companyName);
// brand.setBrandName(brandName);
// 封装对象 3.map集合参数
Map map = new HashMap();
map.put("status" , status);
map.put("companyName",companyName);
map.put("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 branmapper = sqlSession.getMapper(BrandMapper.class);
//4.执行方法
//1.散装参数List<Brand> brands = branmapper.selectByCondition(status,companyName,brandName);
List<Brand> brands = branmapper.selectByCondition(map);
System.out.println(brands);
//5.关闭资源
sqlSession.close();
}
但上述查询有些许不灵活,若用户只想根据一个条件进行查询,那么将无法达到目的。
因此,需要做出相应改变
多条件动态查询
<!--
if:条件判断
test:逻辑表达式
存在问题:如果第一个条件不存在,and会到sql语句中
解决:恒等式:1.加上1=1
2.用</where>标签
-->
<select id="selectByCondition" resultMap="brandResult">
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>
这时就可以只根据其中一个值就能进行查询
单条件动态条件查询
<!--
单条件动态查询语句
-->
<select id="selectByConditionSingle" resultMap="brandResult">
select *
from tb_brand
where
<choose><!--相当于switch-->
<when test="status != null"><!--相当于case-->
status = #{status}
</when>
<when test="companyName != null and companyName != ''">
company_name like#{companyName}
</when>
<when test="brandName != null and brandName != '' ">
brand_name like#{brandName}
</when>
<otherwise><!--相当于default-->
1 = 1;
</otherwise>
</choose>
</select>
添加
<insert id="add">
insert into tb_brand(brand_name,company_name,ordered,description,status)
values (#{brandName},#{companyName},#{ordered},#{description},#{status});
</insert>
<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>
修改
修改全部字段
但上述操作在只修改其中一些字段时会导致其他字段被迫设置为null,这是我们不希望看到的,因此要设置为动态的
修改动态字段
<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>
删除
删除一个
delete
from tb_brand where id = #{id};
</delete>
批量删除
<delete id="delById">
delete
from tb_brand where id = #{id};
</delete>
<delete id="delByIds">
delete from tb_brand where id
in
<foreach collection="array" item="id" separator="," open="(" close=")">
#{id}
</foreach>
;
</delete>
Mybatis参数传递
Mybatis是如何通过@Param来
多个参数:封装为map集合
map.put("arg0",参数值1)
map.put("parm1",参数值1)
map.put("parm2",参数值2)
map.put("arg1",参数值2)
源码分析:ParamNmaeResolver
很好懂,可以自己点进去看
注解开发
直接在java文件中
@Select("select * from `<xiaokasidi>`.tb_brand where id = #{id}")
Brand selectById(int id);