Mybatis(3)-基于代理Dao实现CRUD操作

1、根据id查询

  我们根据上述步骤可以搭建Mybatias环境,我们在搭建好的基础上来进行代理DAO实现增删改查的操作。

  (1)在持久层接口添加findById方法

/**
     * 根据id查询用户
     * @param userId
     * @return
     */
    User findById(Integer userId);

  (2)在用户配置文件中配置

<!-- resultType 属性:用于指定结果集的类型;parameterType 属性:用于指定传入参数的类型;sql 语句中使用#{}字符:它代表占位符,相当于原来 
        jdbc 部分所学的?,都是用于执行语句时替换实际的数据。 -->
    <select >
        parameterType="int">
        select * from user where id = #{uid}
    </select>

 (3)编写Junit测试类并添加测试代码

package com.xhbjava.test;

import java.io.IOException;
import java.io.InputStream;

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 org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.xhbjava.dao.IUserDao;
import com.xhbjava.domain.User;

/**
 * 测试类
 * 
 * @author Mr.wang
 * @date 2020年1月7日
 */
public class MybatisJunitTest {
    InputStream in = null;
    SqlSessionFactory factory = null;
    SqlSession session = null;
    IUserDao userDao = null;

    @Test
    public void testFindOne() {
        // 6.执行查询操作
        User user = userDao.findById(1);
        System.out.println(user);
    }

    @Before
    public void init() throws IOException {
        // 1.读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 2.创建构建者
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3.创建session工厂
        factory = builder.build(in);
        // 4.创建session对象
        session = factory.openSession();
        // 5.创建Dao的代理对象
        userDao = session.getMapper(IUserDao.class);
    }

    @After // 在测试方法执行完成之后执行
    public void destroy() throws Exception {
        session.commit();
        // 7.释放资源
        session.close();
        in.close();
    }

}

2、保存操作

(1)持久层接口中添加保存方法

  

/**
     * 保存用户
     * @param user
     * @return
     */
    int saveUser(User user);
(2)在用户的映射配置文件中配置保存方法
<!-- 保存操作 -->
    <insert id="saveUser" parameterType="com.xhbjava.domain.User">
        insert into
        user(username,birthday,sex,address)
        values(#{username},#{birthday},#{sex},#{address})

    </insert>

  关于细节:

  #{}中内容的写法,由于我们保存方法的参数是 一个 User 对象,此处要写 User 对象中的属性名称它用的是 ognl 表达式。语法格式 #{对象.对象},#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user.而直接写 username。

(3)测试类中添加测试方法

@Test
    public void testSave() {
        User user = new User();
        user.setUsername("张三");
        user.setAddress("北京");
        user.setSex("男");
        user.setBirthday(new Date());
        userDao.saveUser(user);
        System.out.println("保存:"+user);
    }

  测试发现id=null,那我们要显示id,需要做以下处理。

Mybatis(3)-基于代理Dao实现CRUD操作

   由于id是数据库自增实现,所以我们需要在新增后将自动增长长 auto_increment 的值返回。

<insert id="saveUser" parameterType="USER">
<!-- 配置保存时获取插入的 id -->
<selectKey keyColumn="id" keyProperty="id" resultType="int">
select last_insert_id();
</selectKey>
insert into user(username,birthday,sex,address) 
values(#{username},#{birthday},#{sex},#{address})
</insert>

3、用户更新

  (1)在持久层接口中添加更新方法

/**
     * 更新用户
     * 
     * @param user
     * @return
     */
    int updateUser(User user);

(2)在用户的映射配置文件中配置更新方法

<!-- 更新用户 -->
<update id="updateUser" parameterType="com.itheima.domain.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},
address=#{address} where id=#{id}
</update>

(3)添加测试方法

@Test
public void testUpdateUser()throws Exception{
//1.根据 id 查询
User user = userDao.findById(52);
//2.更新操作
user.setAddress("北京市顺义区");
int res = userDao.updateUser(user);
System.out.println(res);
}

(4)执行测试方法

4、用户删除

(1)在持久层接口中添加删除方法

       /**
     *根据用户id删除用户
     * @param userid
     * @return
     */
    int deleteUser(Integer userid);    

(2)在用户映射配置文件中配置

        <!-- 删除用户操作 -->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{uid}
    </delete>    

(3)测试类中添加删除测试方法

@Test
    public void testDeleteUser(){
        int res = userDao.deleteUser(5);
        System.out.println(res);
    }

5、用户模糊查询

(1)持久层接口中添加模糊查询方法

/**
     * 根据用户名模糊查询
     * 
     * @param name
     * @return
     */
    List<User> findUserByName(String name);

(2)在用户映射文件中添加配置

        <!-- 根据姓名模糊查询 -->
    <select id="findUserByName" resultType="com.xhbjava.domain.User" parameterType="String">
        select * from user where username like #{username}
    </select>

(3)测试方法中添加测试

        @Test
    public void testFindUserByName() {
        List<User> users = userDao.findUserByName("张%");
        for(User user:users) {
            System.out.println(user);
        }
    }    

(4)执行测试单元

模糊查询另一种配置方式

(5)在用户映射文件中修改配置

<!-- 根据姓名模糊查询 -->
    <select id="findUserByName" resultType="com.xhbjava.domain.User" parameterType="String">
        <!-- select * from user where username like #{username} -->
        select * from user where username like '%${value}%'
    </select>

(6)测试类中修改代码

@Test
    public void testFindUserByName() {
        List<User> users = userDao.findUserByName("张");
        for(User user:users) {
            System.out.println(user);
        }
    }

(7)#{}与${}的区别

#{}表示一个占位符号,将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号;#方式能够很大程度防止sql注入,$方式无法防止Sql注入。${}表示拼接 sql 串,$将传入的数据直接显示生成在sql中;$方式一般用于传入数据库对象,例如传入表名和列名,还有排序时使用order by动态参数时需要使用$ ,ORDER BY ${columnName};一般能用#的就别用$,若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。在MyBatis中,“${xxx}”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。

6、查询使用聚合函数

(1)在持久层接口中添加查询方法

/**
     * 查询总记录数
     * @return
     */
    int findTotal();

(2)在用户映射文件中配置

<!-- 查询总记录数 -->
    <select id="findTotal" resultType="int">
        select count(*) from user
    </select>

(3)添加测试方法并测试

       @Test
    public void testFindAll() {
        int res = userDao.findTotal();
        System.out.println(res);
    }