JAVA WEB DAY14_ MyBatis(day02)

文章目录

MyBatis

01-根据用户 ID 查询用户-[★★★★]

  • UserMapper 接口代码
public interface UserMapper {
     // 根据id查询用户
     User findUserById(int id);
}
  • 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">
<mapper namespace="com.pkx.dao.UserMapper">
    <!--select标签:用于执行查询语句
            id:对应接口的方法名
            parameterType:对应方法参数的类型,只有一个参数时才需要设置
                   需要在标签体中使用#{}表达式获取参数值
            resultType: 执行sql之后要返回的对象的类型
            标签体:要执行的sql语句
    -->
    <select id="findUserById" parameterType="int" resultType="com.ntt.bean.User">
        select * from user where  id = #{id};
    </select>
</mapper>
  • 在主配置文件中加载接口映射文件
<mappers>
    <!--加载接口映射文件-->
    <mapper resource="com/pkx/dao/UserMapper.xml"></mapper>
</mappers>
  • 测试类代码
public class TestUserMapper {

    private static  SqlSessionFactory sqlSessionFactory = null;
    private SqlSession sqlSession = null;
    private UserMapper userMapper = null;

    // 该方法在所有测试方法执行之前执行1次
    @BeforeClass
    public static void init() throws Exception{
        // 1. 获取字节输入流:关联mybatis主配置文件
        InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 2. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3. 根据字节输入流获取SqlSessionFactory对象
        sqlSessionFactory = builder.build(in);
    }

    // 该方法会在每个测试方法执行之前执行1次
    @Before
    public void before(){
        // 4. 获取SqlSession对象:等价连接对象
        // true:事务自动提交,false:不自动提交,默认值
        sqlSession = sqlSessionFactory.openSession();
        // 5. 获得接口代理对象
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    /**
     * 测试根据id查询用户
     */
    @Test
    public void testFindUserById()throws Exception{
        // 6. 调用接口的方法根据id查询用户
        User user = userMapper.findUserById(1);
        System.out.println("user = " + user);
    }
    // 在每个测试方法执行之后执行1次
    @After
    public  void after(){
        // 7. 关闭连接释放资源
        sqlSession.close();
    }
}

02-配置元素properties基本使用-[★★★★]

properties元素在主配置文件中的作用:

  1. 加载外部属性配置文件:<properties resource="jdbc.properties">
  2. 定义全局的键值对属性,可以在其他使用:<property name="username" value="jack"/>
  • 在 src 目录下准备配置jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/pkx107?characterEncoding=utf8
jdbc.username=root
jdbc.password=root
  • 加载外部属性资源文件
    在主配置文件中加载外部资源文件jdbc.properties,代码如下:
<!--目标:使用properties元素设置全局的属性值和引用外部配置文件
        properties标签作用:
            1. 加载外部属性资源文件:xxx.properties
            2. 定义全局的键值对属性,可以在其他地方使用

        properties元素常用属性:
            resource:加载本地的属性资源文件:资源文件的路径
            url: 加载互联网上的属性资源文件:http://www.baidu.com/
    -->
<properties resource="jdbc.properties">
  <!--如果定义键和外部属性文件的键冲突,则外部文件的优先高于内部定义的-->
  <property name="username" value="jack"/>
</properties>

03-配置元素 typeAliases 基本使用-[★★★★]

  • typeAliases元素的作用?
    给类取别名
    l 内置别名可以直接使用
    l 别名不区分大小写,通常使用小写
  • 在主配置文件中使用typeAliases给类或包下面的类起别名
<typeAliases>
    <!--typeAlias标签:用来给类设置别名
        方式1:给单个类设置别名
            type属性:要设置别名的数据类型:类全名字符串
            alias属性:要设置的别名,不区分大小写,如果不设置该属性值,别名默认就是类名
            package属性:设置要设置别名的包, 自动给该包下的所有类设置别名
                ,别名默认就是类名,不区分大小写

        方式2:扫描包方式给类设置别名
    -->
    <typeAlias type="com.pkx.entity.User" alias="user"></typeAlias>

    <!--扫描包方式给类设置别名:推荐该方法-->
    <package name="com.pkx.entity"/>
</typeAliases>
  • 在接口映射文件中只需要写别名就可以
<select id="selectUserById" resultType="User" parameterType="int">
        select * from user where id = #{id}
</select>

04-配置元素 mappers 基本使用-[★★★★]

  • mappers元素的作用:
    加载接口映射文件

注意事项 :
包扫描方式加载mapper映射文件,说明:
1.要求mapper映射文件,与mapper接口要放在同一个目录
2.要求mapper映射文件的名称,与mapper接口的名称要一致

  • 使用mappers实现扫描包加载映射文件
 <mappers>
    <!--加载接口映射文件-->
   <mapper resource="com/pkx/dao/UserMapper.xml"></mapper>

    <!--使用mappers实现扫描包加载映射文件:推荐使用
        package:设置要扫描的包
        1.要求mapper映射文件,与mapper接口要放在同一个目录
        2.要求mapper映射文件的名称,与mapper接口的名称要一致
        同一个接口映射文件只能采用一种加载方法
    -->
    <package name="com.pkx.dao"/>
</mappers>

使用 Mybatis 实现 CRUD 操作-[★★★★★]

05-方式1- Mapper 接口代理的开发方式

05-01-根据用户名称模糊查询用户-[★★★★★]

  • 需求:使用 mybatis 实现根据用户名称实现模糊查询
  • 实现步骤:
  1. UserMapper 接口增加方法:List<User> findUsersByName(String username);
  2. UserMapper.xml 映射配置文件中配置对应方法
  3. 测试类添加测试方法
  • UserMapper 接口代码
/**
 * 根据用户名称实现模糊查询
 */
List<User> findUsersByName(String username);
  • UserMapper.xml 映射文件代码
<!--根据用户名称实现模糊查询-->
  <select id="findUsersByName"
          parameterType="string"
          resultType="user">
      select * from user where username like #{username}
  </select>
  • 测试类代码
/**
 * 根据用户名称实现模糊查询
 */
@Test
public void testFindUsersByName(){
    // 1. 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 2. 调用接口方法查询数据
    List<User> list = userMapper.findUsersByName("%精%");
    // 3. 遍历输出结果
    for (User user : list) {
        System.out.println(user);
    }
}

05-02-新增用户-[★★★★★]

  1. 添加用户代码执行成功,但是数据库中并没有新增记录,原因是什么?
    因为mybatis事务默认没有提交
  1. SqlSession事务管理的方式有哪些?
    手动提交:sqlSession.commit();
    自动提交:sqlSessionFactory.openSession(true)

注意:如果在同一个方法中,有多个数据库操作,需要使用手动提交的方式。

  • 需求:使用 mybatis 实现添加用户数据到数据库
  • 实现步骤
  1. UserMapper 接口增加方法:void addUser(User user)
  2. UserMapper.xml 映射配置文件中配置对应方法
  3. 测试类添加测试方法
  • UserMapper接口代码
 /**
 *  添加用户
 */
void addUser(User user);
  • UserMapper.xml映射文件代码
<!--添加用户
    insert标签:用来执行insert语句
        id:接口的方法名
        parameterType:方法参数类型
        标签体:要执行的insert语句:insert into user values(null,?,?,?,?);
            占位符?需要使用#{}表达式取代,格式:#{参数类型的属性名}
-->
<insert id="addUser" parameterType="user">
    insert into user values(null,#{username},#{birthday},#{sex},#{address});
</insert>
  • 测试类代码
/**
 * 添加用户
 */
@Test
public void testAddUser(){
    // 1. 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 2. 创建User对象
    User u = new User();
    u.setUsername("如来佛祖111");
    u.setBirthday(Date.valueOf("1980-01-20"));
    u.setAddress("西天灵山");
    u.setSex("男");
    // 3. 保存用户信息
    userMapper.addUser(u);

    // 4. 手动提交事务
    sqlSession.commit();
}

05-03-获取新增记录的主键值-[★★★★★]

  1. 直接在insert标签中添加属性获得主键值适用什么数据库? 主键自增长的数据库
  2. 在insert标签中使用selecKey子标签获得主键值适用什么数据库?不支持主键自增长的数据库
  • Mybatis获取插入记录主键的方式

方式1:直接在insert标签中添加属性:只适合支持自增长字段的数据库(mysql,sqlserver)
 useGeneratedKeys: 使用生成的主键
 keyColumn:表中主键对应的列
 keyProperty:实体类中主键的属性

方式2 :在insert标签中使用selecKey子标签:适合不支持自增长字段的数据库(oracle)
 selectKey标签
  作用:用于执行sql语句查询获取插入的主键值
  属性:
   keyColumn:表中主键对应的列
   keyProperty:实体类中主键的属性
   resultType:主键返回的Java类型
   order:在insert语句执行前,还是执行后获取主键值。
    BEFORE:在insert执行前;
    AFTER: 在insert语句执行后
   last_insert_id():一个msyql数据库的函数用于获取最近一次插入的主键

  • 需求:实现mybatis插入数据后获取主键值
  • 实现步骤
  1. UserMapper接口增加方法:void addUserGetPrimaryKey(User user)
  2. UserMapper.xml映射配置文件中配置对应方法
  3. 测试类添加测试方法
  • UserMapper接口代码
/**
 * 添加用户并获得主键值
 * @param user
 */
void addUserGetPrimaryKey(User user);
void addUserGetPrimaryKey2(User user);
  • UserMapper.xml映射文件代码
<!-- 添加用户并获得主键值
     在insert标签中添加如下属性获得主键值:
        useGeneratedKeys:是否获得主键值 true:获取,false:不获取
        keyColumn:对应数据表中主键列名称
        keyProperty:对应实体类用来封装主键值的属性名
     该种方式只适用支持主键自增长的数据库:比如mysql
-->
<insert
        id="addUserGetPrimaryKey"
        parameterType="user"
        useGeneratedKeys="true"
        keyColumn="id"
        keyProperty="id"
    >
    insert into user values(null,#{username},#{birthday},#{sex},#{address});
</insert>

<!-- 添加用户并获得主键值:适用于数据库不支持自增长的(oracle)
     在insert标签下使用selectKey子标签获得主键值
        selectKey:用来获得插入数据之后的主键值
            keyColumn:数据表的主键列的名称
            keyProperty:实体类用来封装主键值的属性名
            order:在insert语句执行前,还是执行后获取主键值。
                BEFORE:在insert执行前;
                AFTER: 在insert语句执行后
            resultType:设置主键的类型
            last_insert_id():
                一个msyql数据库的函数
                用于获取最近一次插入的主键
-->
<insert id="addUserGetPrimaryKey2" parameterType="user">
    <selectKey
            keyColumn="id"
            keyProperty="id"
            order="AFTER"
            resultType="int"
        >
        select last_insert_id();
    </selectKey>
    insert into user values(null,#{username},#{birthday},#{sex},#{address});
</insert>
  • 测试类代码
/**
 * 添加用户
 */
@Test
public void testAddUser(){
    // 1. 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 2. 创建User对象
    User u = new User();
    u.setUsername("如来佛祖111");
    u.setBirthday(Date.valueOf("1980-01-20"));
    u.setAddress("西天灵山");
    u.setSex("男");
    // 3. 保存用户信息
    userMapper.addUser(u);

    // 4. 手动提交事务
    sqlSession.commit();
}

/**
 * 添加用户并获得主键值
 */
@Test
public void testAddUserGetPrimaryKey(){
    // 1. 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 2. 创建User对象
    User u = new User();
    u.setUsername("如来佛祖222");
    u.setBirthday(Date.valueOf("1980-01-20"));
    u.setAddress("西天灵山");
    u.setSex("男");
    // 3. 保存用户信息
    // userMapper.addUserGetPrimaryKey(u);
    userMapper.addUserGetPrimaryKey2(u);
    System.out.println(u);
    // 4. 手动提交事务
    sqlSession.commit();
}

05-04-根据用户 id 修改用户-[★★★★★]

实现修改的映射配置标签叫什么?update

  • 需求:使用mybatis实现更新id为6号的用户名、生日、性别、地址
  • 实现步骤
  1. UserMapper接口增加方法:void updateUser(User user)
  2. UserMapper.xml映射配置文件中配置对应方法
  3. 测试类添加测试方法
  • UserMapper接口代码
/**
 * 更新用户信息
 */
void updateUser(User user);
  • UserMapper.xml映射文件代码
<!--修改用户:id为6号的用户名、生日、性别、地址
    update标签作用:用于执行更新语句
        id属性:接口的方法名
        parameterType属性:接口方法参数类型
        标签体:要执行的sql语句
-->
<update id="updateUser" parameterType="user">
    update user set username = #{username},
    birthday = #{birthday},sex = #{sex}, address = #{address}
    where id = #{id}
</update>
  • 测试类代码

/**
 * 修改用户
 */
@Test
public void testUpdateUser()throws Exception{
    // 创建用户对象
    User user = new User(
            6,
            "牛魔王",
            Date.valueOf("1998-02-20"),
            "妖",
            "牛魔洞");
    // 更新用户
    userMapper.updateUser(user);

    // 提交事务
    sqlSession.commit();
}

05-05-根据用户 id 删除用户-[★★★★★]

实现删除的映射配置标签叫什么?delete

  • 需求:使用mybatis实现根据用户id删除用户
  • 实现步骤
  1. UserMapper接口增加方法:void deleteUser(Integer id)
  2. UserMapper.xml映射配置文件中配置对应方法
  3. 测试类添加测试方法
  • UserMapper接口代码
/**
 * 根据id删除用户
 */
void deleteUser(Integer id);
  • UserMapper.xml映射文件代码
<!-- delete标签作用:用来执行delete语句
        id:接口方法名
        parameterType:接口方法参数类型
        标签体:要执行的SQL语句:delete from user where id = #{id}
-->
<delete id="deleteUser" parameterType="integer">
    delete from user where id = #{id}
</delete>
  • 测试类代码
/**
 * 根据id删除用户
 */
@Test
public void testDeleteUser(){
    // 1. 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 2. 根据id删除用户
    userMapper.deleteUser(6);
    // 3. 提交事务
    sqlSession.commit();
}

06-输入参数- parameterType -[★★★]

三种参数类型

  • java简单类型:参数只有一个简单类型,那么表达式的名字可以任意:#{任意名字}
  • POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBean,即我们前面封装数据使用的实体类。
  • POJO包装类型:就是在实体类中包含了其它的实体类。

案例01:多个Java简单参数类型查询

  • 需求:使用mybatis实现根据多个简单类型查询条件查询数据

  • 需求:根据姓名和性别查询用户数据(姓名使用模糊查询)

  • 实现步骤

  1. UserMapper接口增加方法:List<User> findByNameAndSex(String name,String sex)
  2. UserMapper.xml映射配置文件中配置对应方法
  3. 测试类添加测试方法
  • UserMapper接口代码
/**
 * 根据用户名和性别查询用户信息:姓名使用模糊查询
 */
List<User> findByNameAndSex(String name,String sex);
  • UserMapper.xml映射文件代码
<!--
    根据用户名和性别查询用户信息:姓名使用模糊查询
    select标签作用:用来执行select语句
        当接口方法有多个参数时,使用下面两种方式获得参数值:
        方式1:(推荐使用)在接口方法中使用@Param给参数设置别名,则使用别名获得参数值:#{参数别名}
        方式2:接口方法中没有给参数区别名时,则可以使用argN或paramN获得参数值
            N:代表是参数索引
            比如:arg0 代表获得第一个参数的值
            比如:arg1 代表获得第二个参数的值
            ...........

            比如:param1 代表获得第一个参数的值
            比如:param2 代表获得第二个参数的值
-->
<select id="findByNameAndSex" resultType="user">
    select * from user where username like #{username} and sex = #{gender}
</select>

<select id="findByNameAndSex02" resultType="user">
    select * from user where username like #{param1} and sex = #{param2}
</select>
  • 测试类代码
/**
 * 根据用户名和性别查询用户信息:姓名使用模糊查询
 */
@Test
public void testFindByNameAndSex(){
    // 1. 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 2. 根据用户名和性别查询用户信息:姓名使用模糊查询
    List<User> list = userMapper.findByNameAndSex02("%精%", "女");
    for (User user : list) {
        System.out.println(user);
    }
}

案例02: POJO包装类型的演示

  • 需求:使用POJO包装类型,实现根据用户名称模糊查询用户
  • 实现步骤
  1. 编写POJO包装类
  2. UserMapper接口增加方法:List<User> findUsersByCondition(QueryVo queryVo)
  3. UserMapper.xml映射配置文件中配置对应方法
  4. 测试类添加测试方法
  • POJO包装类
/**
 * POJO包装类型
 */
public class QueryVo {
    // 包装用户
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}
  • UserMapper接口代码
/**
 * 根据用户名模糊查询用户
 */
List<User> findUsersByCondition(QueryVo queryVo);
  • UserMapper.xml映射文件代码
<!--根据用户名模糊查询用户
    #{pojo包装类型的属性名.属性名}
-->
<select id="findUsersByCondition"
        parameterType="QueryVo"
        resultType="user">
    select * from user where username like #{user.username}
</select>
  • 测试类代码
/**
 * 根据用户名模糊查询
 */
@Test
public void testFindUsersByCondition(){
    // 1. 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 2. 创建查询对象
    QueryVo queryVo = new QueryVo();
    User user = new User();
    user.setUsername("%精%");
    queryVo.setUser(user);
    // 3. 根据用户名模糊查询
    List<User> list = userMapper.findUsersByCondition(queryVo);
    for (User u: list) {
        System.out.println(u);
    }
}
  1. 当参数类型是Java简单类型时,如何获取参数值?
    只有一个参数:#{任意名称}
    多个参数时:
    使用了@Param注解设置别名,则:#{别名}
    没有设置别名时,则:
    #{argN} N从0开始
    #{paramN} N从1开始
  2. 当参数类型是POJO类型时,如何获取参数值?#{类型的属性名}
  3. 当参数类型是POJO包装类型时,如何获取参数值? #{包装类类型属性名.属性名}

07-输出参数-resultType-[★★★]

  • 需求: 查询用户表的总记录数,返回的是一个简单整型数据。
  • 实现步骤
  1. UserMapper接口增加方法:int count()
  2. UserMapper.xml映射配置文件中配置对应方法
  3. 测试类添加测试方法
  • UserMapper接口代码
 /**
     * 查询用户记录数
     */
    int count();
  • UserMapper.xml映射文件代码
<!--查询用户记录数-->
    <select id="count" resultType="int">
        select count(*) from user
    </select>
  • 测试类代码
/**
 * 查询用户记录数
 */
@Test
public void testCount() {
    // 1. 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 2. 查询用户记录数
    System.out.println(userMapper.count());
}
  • POJO类型

数据库返回的字段名称与封装的对象类型的属性名要一模一样才能自动封装。

resultType支持几种返回类型数据?

  • Java简单类型:int/long/string…
  • POJO类型:自定义类型

08-输出参数-resultMap-[★★★]

使用resultType完成输出映射,数据库返回的字段名称与封装的对象类型的属性名要一模一样才能自动封装。否则不能完成映射。两种解决方法:

  1. 使用as给user_name定义别名为username,从而与属性名一致。
  2. 使用resultMap进行映射
  • 需求:使用resultMap解决数据库返回字段名称与封装的对象类型的属性名不同不能封装数据的问题

  • 修改表结构

-- 修改用户表结构,将用户名字段由username改成user_name
alter table user change username user_name varchar(20);
select * from user;

在这里插入图片描述

  • 执行根据id查询用户测试
@Test
public void testFindUserById() throws IOException {
    // 获得接口代理对象
    UserMapper userMapper = session.getMapper(UserMapper.class);
    // 根据id查询用户
    User user = userMapper.findUserById(1);
    System.out.println(user);
}
  • 执行结果如下:

在这里插入图片描述

方式一:使用别名解决

  • 修改映射文件代码如下
<select id="findUserById" parameterType="int" resultType="user">
   select id, user_name as username,birthday, sex, address from user where  id = #{id};
 </select>

方式二:使用resultMap解决

resultMap用于配置sql语句中字段(列)的名称与java对象中属性名称的对应关系。本质上还是要把执行结果映射到java对象上。

  • 修改配置映射文件代码如下
<!--resultMap标签作用:用来设置数据表字段与实体类属性的对应关系
        id标签:用来设置数据表主键字段与实体类主键属性的关系
            column:数据表的主键字段名
            property:实体类的主键属性名

        result标签:用来设置数据表非主键字段与实体类属性的关系
            column:数据表的字段名
            property:实体类属性名
        须知:如果字段名和属性名相同,可以省略
-->
<resultMap id="userMap" type="user">
    <id column="id" property="id"></id>
    <result column="user_name" property="username"></result>
    <result column="birthday" property="birthday"></result>
    <result column="sex" property="sex"></result>
</resultMap
  
<select id="findUserById" parameterType="int" resultMap="userMap">
        select * from user where id = #{id}
    </select>
  • 测试代码
@Test
public void testFindUserById() throws IOException {
    // 获得接口代理对象
    UserMapper userMapper = session.getMapper(UserMapper.class);
    // 根据id查询用户
    User user = userMapper.findUserById(1);
    System.out.println(user);
}
  1. resultType指定的实体类适合封装什么样的数据?
    resultType封装数据库返回的字段与实体类属性名一模一样的
  2. resultMap适合封装什么样的数据?
    resultMap封装数据库返回的字段与实体类属性名不一样的

09-方式2-传统Dao实现类的开发方式-[★]

1.1 目标
  • 使用传统Dao实现类实现用户表(user)的增删改查操作。
  1. 根据用户id查询用户

  2. 根据用户id修改用户

  3. 根据用户id删除用户

  4. 新增一个用户

1.2 实现步骤
  • 复制上面的项目产生一个新项目
  • 编写IUserDao接口
  • 编写映射文件:IUserDao.xml
  • 编写UserDaoImpl类实现IUserDao接口
  • 在sqlMapConfig.xml中加载映射文件
  • 编写测试类进行测试
1.3 UserMapper接口代码
/**
 * 数据访问层接口
 */
public interface UserMapper {

    /**
     * 根据用户id查询用户
     */
    User findById(int id);

    /**
     * 根据id修改用户
     */
    int updateUser(User user);

    /**
     * 根据id删除用户
     */
    int deleteUser(int id);

    /**
     * 添加用户
     */
    int addUser(User user);
}
1.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">
<mapper namespace="com.pkx.dao.UserMapper">
    <resultMap id="userMap" type="user">
        <id column="id" property="id"></id>
        <result column="user_name" property="username"></result>
    </resultMap>

    <!--根据用户id查询用户-->
    <select id="findById" parameterType="int" resultMap="userMap">
        select * from user where id = #{id}
    </select>

    <!--根据id修改用户-->
    <update id="updateUser" parameterType="user">
        update user set user_name = #{username},sex=#{sex},address=#{address},birthday=#{birthday}
        where id = #{id}
    </update>

    <!--根据id删除用户-->
    <delete id="deleteUser" parameterType="int">
        delete from user where id = #{id}
    </delete>

    <!--添加用户-->
    <insert id="addUser" parameterType="user">
        insert into user values(null,#{username},#{birthday},#{sex},#{address})
    </insert>
</mapper>
1.5 UserDaoImpl实现类代码
/**
 * 数据访问层接口实现类
 */
public class UserMapperImpl implements UserMapper {

    private SqlSession sqlSession;

    public UserMapperImpl(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public User findById(int id) {
        // 查询一个对象
        // 参数1:namespace+"."+id
        // 参数2:要返回结果的类型
        return sqlSession.selectOne("com.pkx.dao.UserMapper.findById", User.class);
    }

    @Override
    public int updateUser(User user) {
        int row = sqlSession.update("com.pkx.dao.UserMapper.updateUser",user);
        sqlSession.commit();
        sqlSession.close();
        return row;
    }

    @Override
    public int deleteUser(int id) {
        int row = sqlSession.delete("com.pkx.dao.UserMapper.deleteUser", id);
        sqlSession.commit();
        sqlSession.close();
        return row;
    }

    @Override
    public int addUser(User user) {
        int row = sqlSession.insert("com.pkx.dao.UserMapper.addUser", user);
        sqlSession.commit();
        sqlSession.close();
        return row;
    }

}
1.6 在sqlMapConfig.xml中加载映射文件
<mappers>
    <package name="com.pkx.dao"/>
</mappers>
1.7 测试类代码
public class TestUserMapper {

    private static  SqlSessionFactory sqlSessionFactory = null;
    private SqlSession sqlSession = null;
    private UserMapper userMapper = null;

    // 该方法在所有测试方法执行之前执行1次
    @BeforeClass
    public static void init() throws Exception{
        // 1. 获取字节输入流:关联mybatis主配置文件
        InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 2. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3. 根据字节输入流获取SqlSessionFactory对象
        sqlSessionFactory = builder.build(in);
    }

    // 该方法会在每个测试方法执行之前执行1次
    @Before
    public void before(){
        // 4. 获取SqlSession对象:等价连接对象
        // true:事务自动提交,false:不自动提交,默认值
        sqlSession = sqlSessionFactory.openSession();
        // 5. 创建接口实现类对象
        userMapper = new UserMapperImpl(sqlSession);
    }


    /**
     * 测试:根据id查询用户
     */
    @Test
    public void testFindById(){
        System.out.println(userMapper.findById(2));
    }

    /**
     * 测试:根据id修改用户
     */
    @Test
    public void testUpdateUser(){
        User user = new User(2, "铁扇公主", Date.valueOf("1988-10-20"),"男","芭蕉洞");
        System.out.println(userMapper.updateUser(user));
    }

    /**
     * 测试:根据id删除用户
     */
    @Test
    public void testDeleteUser(){
        System.out.println(userMapper.deleteUser(2));
    }

    /**
     * 测试:根据添加用户
     */
    @Test
    public void testAddUser(){
        User user = new User(0,"铁扇公主", Date.valueOf("1988-10-20"),"男","芭蕉洞");
        System.out.println(userMapper.addUser(user));
    }

}

10-方式3-注解的开发方式-[★★★★★]

  • 需求:使用注解方式实现用户表(user)的增删改查操作。
  1. 根据用户id查询用户

  2. 根据用户id修改用户

  3. 根据用户id删除用户

  4. 新增一个用户

注解@Select基本使用-[★★★★★]

  • 需求 :根据用户id查询用户
  • UserMapper接口代码
public interface UserMapper {
    // 1)  根据用户id查询用户
    @Select("select id,user_name username,birthday,sex, address from user where id = #{id}")
    User findUserById(int id);
}
  • 测试类代码
public class TestUserMapper {

    private static  SqlSessionFactory sqlSessionFactory = null;
    private SqlSession sqlSession = null;
    private UserMapper userMapper = null;

    // 该方法在所有测试方法执行之前执行1次
    @BeforeClass
    public static void init() throws Exception{
        // 1. 获取字节输入流:关联mybatis主配置文件
        InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 2. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3. 根据字节输入流获取SqlSessionFactory对象
        sqlSessionFactory = builder.build(in);
    }

    // 该方法会在每个测试方法执行之前执行1次
    @Before
    public void before(){
        // 4. 获取SqlSession对象:等价连接对象
        // true:事务自动提交,false:不自动提交,默认值
        sqlSession = sqlSessionFactory.openSession();
        // 5. 创建接口实现类对象
        userMapper = sqlSession.getMapper(UserMapper.class);
    }


    /**
     * 测试:根据id查询用户
     */
    @Test
    public void testFindById(){
        System.out.println(userMapper.findById(9));
    }

    /**
     * 测试:根据id修改用户
     */
    @Test
    public void testUpdateUser(){
        User user = new User(3, "铁扇公主", Date.valueOf("1988-10-20"),"男","芭蕉洞");
        System.out.println(userMapper.updateUser(user));
    }

    /**
     * 测试:根据id删除用户
     */
    @Test
    public void testDeleteUser(){
        System.out.println(userMapper.deleteUser(9));
    }

    /**
     * 测试:根据添加用户
     */
    @Test
    public void testAddUser(){
        User user = new User(0,"铁扇公主02", Date.valueOf("1988-10-20"),"男","芭蕉洞");
        System.out.println(userMapper.addUser(user));
    }

    @After
    public void after(){
        sqlSession.commit();
        sqlSession.close();
    }

}

注解@Update基本使用-[★★★★★]

  • 需求:根据用户id修改用户
  • UserMapper接口代码
 @Update("update user set user_name = #{username},birthday = #{birthday}, " +
            "sex = #{sex},address = #{address} where id = #{id}")
int updateUser(User user);
  • 测试类代码
@Test
public void testUpdateUser(){
    // 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 创建用户对象
    User user = new User();
    user.setUsername("孙悟空");
    user.setBirthday(Date.valueOf("1999-01-01"));
    user.setId(7);
    user.setSex("女");
    user.setAddress("东莞花果山");
    System.out.println(userMapper.updateUser(user));
    // 提交事务
    sqlSession.commit();
}

注解@Delete基本使用-[★★★★★]

  • 需求:根据用户id删除用户
  • UserMapper接口代码
// 目标:根据用户id删除用户
@Delete("delete from user where id = #{id}")
int deleteUser(int id);
  • 测试类代码
@Test
public void testDeleteUser(){
    // 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 删除8号用户
    System.out.println(userMapper.deleteUser(8));
    // 提交事务
    sqlSession.commit();
}

注解@Insert基本使用-[掌握]

  • 需求:新增用户

  • UserMapper接口代码

// 目标:新增用户
@Insert("insert into user values(null,#{username},#{birthday},#{sex},#{address})")
@SelectKey(
        statement = "select last_insert_id();", // 要执行的SQL语句
        keyColumn = "id", // 数据表主键列名
        keyProperty = "id", // 实体类的主键属性名
        before = false,  // 插入后才获取主键值
        resultType = int.class   // 主键的类型
)
int insertUser(User user);
  • 测试类代码
@Test
public void testInsertUser(){
    // 获得接口代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 创建用户对象
    User user = new User();
    user.setUsername("孙悟333");
    user.setBirthday(Date.valueOf("1999-01-01"));
    user.setSex("女");
    user.setAddress("东莞花果山");
    System.out.println(userMapper.insertUser(user));

    System.out.println("user = " + user);
    // 提交事务
    sqlSession.commit();
}

在这里插入图片描述

11-Mybatis动态SQL01-if与where标签-[★★★★★]

  1. if标签作用:判断参数是否有值,有则拼接SQL片段,否则不拼接
  2. where标签作用:
    1.相当于sql语句中的where关键字
    2.根据传入的参数情况,智能的去掉多余的and、or、where关键字
  • 需求:使用if和where标签实现动态SQL语句的编写

  • if标签作用
    判断传入的参数情况,拼装sql语句片段。如果查询属性有值,则查询,没有则不查询。

  • where标签作用
    1.相当于sql语句中的where关键字
    2.根据传入的参数情况,智能的去掉多余的and、or、where关键字

  • 实现步骤

  1. 复制上一个项目产生新的项目
  2. IUserDao增加findByCondition(User user)实现多条件查询用户数据
  3. IUserDao.xml映射配置文件中配置对应方法
  4. 测试类代码
  • 实现代码
  • IUserDao接口代码
public interface IUserDao {

    // 根据多条件查询用户
    List<User>  findByCondition(User user);
}

+IUserDao.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.pkx.dao.IUserDao">

    <!--根据多条件查询用户
        根据id和username查询用户
        id有值,则将id作为查询条件
        username有值,则将username作为查询条件
    -->
    <!--
 		if标签作用:判断参数是否有值,有值则进行SQL片段的拼接
    		test:用来设置判断条件,条件true则执行标签体的代码
     -->
    <select id="findByCondition" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="id != null and id != ''">
                 and id > #{id}
            </if>
            <if test="username != null and username != ''">
                 and username like #{username}
            </if>
        </where>
    </select>
</mapper>
  • 测试类代码
// 根据多条件查询用户
@Test
public void testFindByCondition(){
    // 接口实现类对象
    IUserDao userDao = sqlSession.getMapper(IUserDao.class);
    // 创建用户对象
    User user = new User();
    user.setId(7);
    user.setUsername("%如来佛祖%");
    // 根据多条件查询用户
    List<User> List = userDao.findByCondition(user);
    for (User u : List) {
        System.out.println(u);
    }
}

13-Mybatis动态SQL02-foreach标签-[★★★★★]

foreach的作用:循环生成重复结构的动态sql

  • 如何在映射文件编写具有如下查询条件的SQL语句?
where id in (41,42,43,44,45,46,...)
-- 或者
where id = 41 or id = 42 or id=43 or id = 44 or id = 45 or id = 46 ...
  • 需要生成目标sql
where id in (?,?,?,?,?,?,...)
-- 或者
where id = ? or id = ? or id=? or id = ? or id = ? or id = ? ...
  • 使用foreach循环标签解决

  • foreach标签作用
    循环处理参数(集合或数组)

  • 需求说明:实现根据多个id批量查询用户

  • 实现步骤

  1. IUserDao增加findByCondition2(List<Integer> ids)方法实现批量查询用户
  2. IUserDao.xml映射配置文件中配置对应方法
  3. 测试类代码
  • IUserDao接口代码
// 批量查询用户
 List<User>  findByCondition2(@Param("ids") List<Integer> ids);
  • IUserDao.xml 映射文件代码

   <!-- // 批量查询用户
    格式1 :id in ( 41,42,43,44,45,46,...)
    格式2 :id = 41 or id = 42 or id=43 or id = 44 or id = 45 or id = 46 ...
    foreach标签作用:遍历集合或数组
        collection:要遍历的数组或集合
        open:循环的开始部分
        close:循环的结束部分
        item:遍历的元素
        separator:循环体的分隔符
    -->
    <select id="findByCondition2" parameterType="list" resultType="user">
        select * from user
        <where>
           <!-- <foreach collection="list"
                     close=")"
                     item="id"
                     open="id in ( "
                     separator=",">
                #{id}
            </foreach>-->
           <foreach collection="list" item="id" separator=" or ">
                id = #{id}
           </foreach>
        </where>
    </select>
  • 测试类代码
@Test
    public void testFindByCondition02(){
        // 接口实现类对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        // 创建集合对象
        List<Integer> ids = new ArrayList<>();
        ids.add(10);
        ids.add(12);
        // 根据多条件查询用户
        List<User> List = userDao.findByCondition2(ids);
        for (User u : List) {
            System.out.println(u);
        }
    }

13-Mybatis动态SQL03-sql与include标签-[★★★★★]

sql标签和include标签一起使用可以实现:简化重复sql语句的作用

  • sql和include标签作用
    sql标签:定义公共的sql语句片段
    include标签:引用上面定义的sql标签

  • sql 中可将重复的使用sql标签提取出来,使用时用include标签引用即可,最终达到 sql重用的目的

  • IUserDao.xml映射配置文件中配置优化代码片段

    <sql id="usertable" >select * from user</sql>
    
    
    <select id="findByCondition2" parameterType="list" resultType="User">
        <include refid="usertable"></include>
        <where>
            <foreach collection="ids" item="id" separator="or">
                id = #{id}
            </foreach>
        </where>
    </select>

14-Mybatis动态SQL04-注解实现-[★]

//一个命名参数
@Select("<script> select * from user <where> <if test='id != 0'> and id=#{id}</if></where></script>")
User findById(@Param("id") int id);

//多个命名参数
@Select("<script> select * from user <where> <if test='id != 0'> and id=#{id}</if><if test='name!=null'> and username like #{name} </if> </where></script>")
User findById2(@Param("id") int id, @Param("name") String name);

//一个没有命名的参数,使用_parameter代替传入的参数值
@Select("<script> select * from user <where> <if test=\"_parameter != 0\"> and id=#{id}</if></where></script>")
User findById3(int id);

//多个没有命名参数
@Select("<script> select * from user <where> <if test='arg0 != 0'> and id=#{arg0}</if><if test='arg1!=null'> and username like #{arg1} </if> </where></script>")
User findById4(int id, String name);

15_Mybatis内置连接池概述-[★]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值