Mybatis

配置mybatis-config.xml文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://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://localhost:3306/mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载SQL映射文件-->
<mapper resource="UserMapper.xml"/>
<!-- 使用Mapper 代理进行简化配置-->
<!-- <package name="com/dragonkeep/mapper"/>-->
</mappers>
</configuration>

配置对应类的Mapper.xml文件,实现SQL语句和xml文件的映射,下面以UserMapper.xml文件为例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace:名称空间
id:SQL语句的唯一表示
-->
<mapper namespace="test">
<select id="selectAll" resultType="com.dragonkeep.pojo.User">
select * from tb_user;
</select>
</mapper>

demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1.加载mybatis的核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(resourceAsStream);

//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();

//3.执行sql
List<User> users = sqlSession.selectList("test.selectAll");

System.out.println(users);

//4.释放资源
sqlSession.close();

Mapper 代理开发

编写UserMapper接口:

1
2
3
4
5
6
7
8
9
10
11
package com.dragonkeep.mapper;

import com.dragonkeep.pojo.User;

import java.util.List;

public interface UserMapper {

List<User> selectAll();
}

使用和UserMapper接口编译后一个目录下的UserMapper.xml配置文件。
目录结构:

  • java
    • com.dragonkeep.mapper
      • UserMapper
  • resource
    • com.dragonkeep.mapper
      • UserMapper.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace:名称空间
id:SQL语句的唯一表示
-->
<mapper namespace="com.dragonkeep.mapper.UserMapper">
<select id="selectAll" resultType="com.dragonkeep.pojo.User">
select * from tb_user;
</select>
</mapper>

修改mybastis-config.xml文件mapper属性对应文件。

1
<mapper resource="com/dragonkeep/mapper/UserMapper.xml"/>

demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.dragonkeep;


import com.dragonkeep.mapper.UserMapper;
import com.dragonkeep.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
* Mybatis 代理demo2
*/
public class MybatisDemo2 {
public static void main(String[] args) throws IOException {
//1.加载mybatis的核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(resourceAsStream);

//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();

//3.执行sql
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectAll();

System.out.println(users);

//4.释放资源
sqlSession.close();
}
}

配置文件完成增删改查

导入简单的SQL文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use mybatis;
drop table if exists tb_brand;

create table tb_brand(

id int primary key auto_increment,

brand_name varchar(20),

company_name varchar(28),

ordered int,

description varchar(188),

status int
);
insert into tb_brand (brand_name,company_name,ordered,description,status) VALUES("三只松鼠",'三只松面股份有限公司',5,"好吃不上火",0),
('华为','华为技术有限公司',100,'年为致力于把数字世界带入每个人、每个家庭、每个组织,均连万物互联的智能世界',1),
('小米','小米科技有服公司',50,"are you ok",1);
select * from tb_brand;

查询表所有数据

编写BrandMapper接口:

1
2
3
4
5
6
7
8
9
10
11
12
package com.dragonkeep.mapper;

import com.dragonkeep.pojo.Brand;

import java.util.List;

public interface BrandMapper {
/*
* 查询所有
* */
List<Brand> selectAll();
}

添加BrandMapper.xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace:名称空间
id:SQL语句的唯一表示
-->
<mapper namespace="com.dragonkeep.mapper.BrandMapper">

<select id="selectAll" resultType="com.dragonkeep.pojo.Brand">
select *
from tb_brand;
</select>
</mapper>

mybastis-config.xml中导入BrandMapper.xml文件。

1
<mapper resource="com/dragonkeep/mapper/BrandMapper.xml"/>

常见问题及其解决

数据库表名和实体类的属性名称不一样,则不能自动封装数据。
解决方法:

  • 起别名:对不一样的列起列名,让别名和实体类属性一样。
  • 缺点每次都要定义别名

使用<sql>标签进行起别名,然后使用<include>标签引用到SQL查询字段。

1
2
3
4
5
6
7
<sql id="selectAll">
id,brand_name as brandName,company_name as companyName,ordered,description,status
</sql>
<select id="selectAll" resultType="com.dragonkeep.pojo.Brand">
select <include refid="selectAll"></include>
from tb_brand;
</select>

使用<resultMap>标签映射,将<select>标签中的resulType属性改为resultMap,设置为<resultMap>标签的id属性。<result>标签的column为表的字段名映射到property为类的属性名。

1
2
3
4
5
6
7
8
<resultMap id="brandResultMap" type="com.dragonkeep.pojo.Brand">
<result column="brand_name" property="brandName"/>
<result column="company_name" property="companyName"/>
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *
from tb_brand;
</select>

查询表中指定数据

BrandMapper.xml添加指定查询语句:
有关#{}${}的区别:

  • #{}使用的是?进行占位,预编译SQL语句,可以简单类别PreparedStatement语句。相对安全。
  • ${}是直接拼接SQL语句,类比Statement语句。相对危险,存在SQL注入。
    1
    2
    3
    4
    5
    <select id="selectById" resultMap="brandResultMap">
    select *
    from tb_brand
    where id = #{id};
    </select>
    BrandMapper接口中配置有参的方法:
    1
    Brand selectById(int id);

指定多条件查询表

接受多个参数的条件进行查询,在BrandMapper接口类编写方法时需要进行映射或者指定类或者指定Map。
对应的SQL映射文件:

1
2
3
4
5
6
7
8
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
where
status=#{status}
and company_name like #{companyName}
and brand_name like #{brandName};
</select>

使用映射:

1
List<Brand>selectByCondition(@Param("status")int Status,@Param("companyName")String companyName,@Param("brandName")String brandName);

使用指定类:

1
List<Brand>selectByCondition(Brand brand);

使用指定Map:

1
List<Brand>selectByCondition(Map map);

动态SQL

概念:SQL会随着用户输入查询的变化而变化,称为动态SQL。

多条件的动态查询

where语句查询中,可能用户只输入指定字段的匹配,而不输入全部字段,这时需要使用<where>标签和if标签进行配合使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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>

注意:<where>能自动解决逻辑运算符的问题,<if>进行条件判断。

单条件下动态查询

如果在查询字段中,有多个选择一个字段进行匹配的话,可以使用<choose><when>.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<select id="selectByConditionSingle" resultMap="brandResultMap">
select *
from tb_brand
where
<choose><!-- 类别switch语法-->
<when test="status!=null">
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>
1 = 1
</otherwise>
</choose>
</select>

添加数据

1
2
3
4
<insert id="add">
insert into tb_brand(brand_name,company_name,ordered,description,status)
values (#{brandName},#{companyName},#{ordered},#{description},#{status});
</insert>

mybatis事务:
openSession():默认开启事务,进行增删改查后需要使用sqlSession.commit()手动提交。
openSession(true):可以设置自动提交。
返回添加数据的主键值
<insert>标签中添加useGeneratedKeys="true" keyProperty="id"

1
2
3
4
<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>

这样就可以在brand实例中使用getID获取到主键id的值。

修改数据

修改全部字段:

1
2
3
4
5
6
7
8
9
10
<update id="update">
update tb_brand
set
brand_name=#{brandName},
company_name=#{companyName},
ordered=#{ordered},
description=#{description},
status=#{status}
where id =#{id};
</update>

修改动态字段:
只修改部分字段,不用每次都修改全部字段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<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>
where id =#{id};
</set>

批量删除

1
2
3
4
5
6
7
<delete id="deleteByIds">
delete from tb_brand where id in(
<foreach collection="ids" item="id" separator=",">
#{id}
</foreach>
)
</delete>

<foreach>遍历删除的id数组,使用separator来添加分隔符。

注解开发

注解用于简单的SQL语句,复杂的SQL,例如动态SQL,最好使用XML来进行映射配置。
对比一下使用注解和xml方式。
使用注解:

1
2
@Select("select * from tb_brand where id=#{id}")
Brand selectById(int id);

只需要在接口方法上添加注解:

  • @Select
  • @Update
  • @Delete
  • @Insert

使用xml

1
2
3
<select id="selectById" resultType="com.dragonkeep.pojo.Brand">
select * from tb_brand where id =#{id};
</select>