mybatis

mybatis

1.什么是mybatis

mybatis是一款优秀的持久层框架,用于简化JDBC的开发

2.使用入门

【第一步】准备工作:创建数据库和表

【第二步】创建springboot工程,引入Mybatis的相关依赖,配置Mybatis(数据库连接信息)

在springboot项目中,可以编写application.properties文件,配置数据库连接信息

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234

【第三步】实体类User、编写Mapper接口、SQL语句(注解/XML)

  • 实体类的属性名与表中的字段名一一对应。
  • @Mapper注解:表示是mybatis中的Mapper接口,框架会自动生成接口的实现类对象(代理对象),并给交Spring的IOC容器管理
  • @Select注解:代表的就是select查询,用于书写select查询语句

@Mapper
public interface UserMapper {
    
    //查询所有用户数据
    @Select("select id, name, age, gender, phone from user")
    public List<User> list();
    
}

【第四步】单元测试

在创建出来的SpringBoot工程中,在src下的test目录下,已经自动帮我们创建好了测试类 ,并且在测试类上已经添加了注解 @SpringBootTest,代表该测试类已经与SpringBoot整合。

该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器)。我们要测试那个bean对象,就可以直接通过@Autowired注解直接将其注入进行,然后就可以测试了。

@SpringBootTest
public class MybatisQuickstartApplicationTests {
    
    @Autowired
    private UserMapper userMapper;
    
    @Test
    public void testList(){
        List<User> userList = userMapper.list();
        for (User user : userList) {
            System.out.println(user);
        }
    }

}

3.什么是JDBC?

JDBC: ( Java DataBase Connectivity ),就是使用Java语言操作关系型数据库的一套API。

原始的JDBC程序是如何操作数据库的

  1. 注册驱动

  2. 获取连接对象

  3. 执行SQL语句,返回执行结果

  4. 处理执行结果

  5. 释放资源

public class JdbcTest {
    @Test
    public void testJdbc() throws Exception {
        //1. 注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2. 获取数据库连接
        String url="jdbc:mysql://127.0.0.1:3306/mybatis";
        String username = "root";
        String password = "1234";
        Connection connection = DriverManager.getConnection(url, username, password);

        //3. 执行SQL
        Statement statement = connection.createStatement(); //操作SQL的对象
        String sql="select id,name,age,gender,phone from user";
        ResultSet rs = statement.executeQuery(sql);//SQL查询结果会封装在ResultSet对象中

        List<User> userList = new ArrayList<>();//集合对象(用于存储User对象)
        //4. 处理SQL执行结果
        while (rs.next()){
            //取出一行记录中id、name、age、gender、phone下的数据
            int id = rs.getInt("id");
            String name = rs.getString("name");
            short age = rs.getShort("age");
            short gender = rs.getShort("gender");
            String phone = rs.getString("phone");
            //把一行记录中的数据,封装到User对象中
            User user = new User(id,name,age,gender,phone);
            userList.add(user);//User对象添加到集合
        }
        //5. 释放资源
        statement.close();
        connection.close();
        rs.close();

        //遍历集合
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

-----------------------------------------------------------------------------------------------------------------------

DriverManager(类):数据库驱动管理类。

  • 作用:

    1. 注册驱动

    2. 创建java代码和数据库之间的连接,即获取Connection对象

Connection(接口):建立数据库连接的对象

  • 作用:用于建立java程序和数据库之间的连接

Statement(接口): 数据库操作对象(执行SQL语句的对象)。

  • 作用:用于向数据库发送sql语句

ResultSet(接口):结果集对象(一张虚拟表)

  • 作用:sql查询语句的执行结果会封装在ResultSet中

4.数据库连接池

4.1什么是数据库连接池

数据库连接池是个容器,负责分配、管理数据库连接(Connection)

  • 程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象

允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

  • 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)

释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏

  • 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象

4.2连接池的好处

  1. 资源重用

  2. 提升系统响应速度

  3. 避免数据库连接遗漏



5.mybatis基础操作-删除

  • SQL语句

-- 删除id=17的数据
delete from emp where id = 17;

  • 接口方法

@Mapper
public interface EmpMapper {
    
    //@Delete("delete from emp where id = 17")
    //public void delete();
    //以上delete操作的SQL语句中的id值写成固定的17,就表示只能删除id=17的用户数据
    //SQL语句中的id值不能写成固定数值,需要变为动态的数值
    //解决方案:在delete方法中添加一个参数(用户id),将方法中的参数,传给SQL语句
    
    /**
     * 根据id删除数据
     * @param id    用户id
     */
    @Delete("delete from emp where id = #{id}")//使用#{key}或${key}方式获取方法中的参数值
    public void delete(Integer id);
    
}

 

@Delete注解:用于编写delete操作的SQL语句

  • 测试

在单元测试类中通过@Autowired注解注入EmpMapper类型对象

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired //从Spring的IOC容器中,获取类型是EmpMapper的对象并注入
    private EmpMapper empMapper;

    @Test
    public void testDel(){
        //调用删除方法
        empMapper.delete(16);
    }

}

如何打开日志输出

打开application.properties文件

#指定mybatis输出日志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

预编译的好处

性能更高:预编译SQL,编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句时,不会再次编译。(只是输入的参数不同)

更安全(防止SQL注入):将敏感字进行转义,保障SQL的安全性。

#{}和${}之间的区别?
#{}占位符在程序运行过程中会被翻译成?占位符,不会出现SQL注入漏洞问题,能预编译SQL。
${}占位符在程序行过程中不会被翻译成?占位符,是直接拼接值,可能出现SQL注入漏洞问题,不能预编译SQL

6.mybatis基础操作-新增

@Options(useGeneratedKeys = true,keyProperty = "id")

@Insert注解书写sql语句

useGeneratedKeys = true 表示需要获取生成的主键值。

keyProperty = "id"   将生成的主键值赋值给参数对象的id属性,也就是emp对象的id属性

 @Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into emp( username, name, image,gender, job, entrydate,update_time ,create_time ,dept_id) values (#{username},#{name},#{image},#{gender},#{job},#{entrydate},#{createTime},#{updateTime},#{deptId})")
void insert(Emp emp);

 

7.mybatis基础操作更新

  @Update("update emp set username=#{username}, name=#{name}, gender=#{gender}, image=#{image}, job=#{job}, entrydate=#{entrydate}, dept_id=#{deptId}, update_time=#{updateTime} where id=#{id}")
    public void update(Emp emp);

8.mybatis基础操作查询

SQL语句:select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp;

接口方法:

@Mapper
public interface EmpMapper {
    @Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")
    public Emp getById(Integer id);
}

测试:

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testGetById(){
        Emp emp = empMapper.getById(1);
        System.out.println(emp);
    }
}

 

在测试的过程中,我们会发现有几个字段(deptId、createTime、updateTime)是没有数据值的

 

原因如下:

 

  • 实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装。

  • 如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。

 

解决方案:

 

 

起别名  在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样

 

@Select("select id, username, password, name, gender, image, job, entrydate, " +
        "dept_id AS deptId, create_time AS createTime, update_time AS updateTime " +
        "from emp " +
        "where id=#{id}")
public Emp getById(Integer id);

 

结果映射  通过 @Results及@Result 进行手动结果映射

 

@Results({@Result(column = "dept_id", property = "deptId"),
          @Result(column = "create_time", property = "createTime"),
          @Result(column = "update_time", property = "updateTime")})
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")
public Emp getById(Integer id);

 

开启驼峰命名

打开application.properties文件

 

# 在application.properties中添加:
mybatis.configuration.map-underscore-to-camel-case=true

模糊查询

使用MySQL提供的字符串拼接函数:concat('%' , '关键字' , '%')

@Mapper
public interface EmpMapper {

    @Select("select * from emp " +
            "where name like concat('%',#{name},'%') " +
            "and gender = #{gender} " +
            "and entrydate between #{begin} and #{end} " +
            "order by update_time desc")
    public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);

}

9.Mybatis的XML配置文件

9.1三个规范

 

  1. XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)

  2. XML映射文件的namespace属性为Mapper接口全限定名一致

  3. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。

<?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">
<mapper namespace="">
 
</mapper>

在Mybatis中提供了很多实现动态SQL的标签,我们学习Mybatis中的动态SQL就是掌握这些动态SQL标签。

9.2where标签和if标签

<if test="条件表达式">
   要拼接的sql语句
</if>

<select id="list" resultType="com.itheima.pojo.Emp">
        select * from emp
        <where>
    
             <if test="name != null">
                 name like concat('%',#{name},'%')
             </if>
             <if test="gender != null">
                 and gender = #{gender}
             </if>
             <if test="begin != null and end != null">
                 and entrydate between #{begin} and #{end}
             </if>
    </where>
        order by update_time desc
</select>

9.3set标签

<?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">
<mapper namespace="com.itheima.mapper.EmpMapper">

    <!--更新操作-->
    <update id="update">
        update emp
        <!-- 使用set标签,代替update语句中的set关键字 -->
        <set>
            <if test="username != null">
                username=#{username},
            </if>
            <if test="name != null">
                name=#{name},
            </if>
            <if test="gender != null">
                gender=#{gender},
            </if>
            <if test="image != null">
                image=#{image},
            </if>
            <if test="job != null">
                job=#{job},
            </if>
            <if test="entrydate != null">
                entrydate=#{entrydate},
            </if>
            <if test="deptId != null">
                dept_id=#{deptId},
            </if>
            <if test="updateTime != null">
                update_time=#{updateTime}
            </if>
        </set>
        where id=#{id}
    </update>
</mapper>

9.4foreach标签

<?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">
<mapper namespace="com.itheima.mapper.EmpMapper">
    <!--删除操作-->
    <delete id="deleteByIds">
        delete from emp where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>
</mapper>

9.5sql和include标签

我们可以对重复的代码片段进行抽取,将其通过<sql>标签封装到一个SQL片段,然后再通过<include>标签进行引用。

  • <sql>:定义可重用的SQL片段

  • <include>:通过属性refid,指定包含的SQL片段

<sql id="commonSelect">
     select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp
</sql>

<select id="list" resultType="com.itheima.pojo.Emp">
    <include refid="commonSelect"/>
    <where>
        <if test="name != null">
            name like concat('%',#{name},'%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
    </where>
    order by update_time desc
</select>

 

posted on 2023-04-08 21:08  zl子路  阅读(40)  评论(0)    收藏  举报