mybatis基本使用——基于代理Dao的CRUD操作

使用 Mybatis 开发 Dao,通常有两个方法,即原始 Dao 开发方式和 Mapper 接口代理开发方式。 
而现在主流的开发方式是接口代理开发方式,这种方式总体上更加简便。 

根据 ID 查询

1.在持久层接口中添加 findById 方法

/**
 * 持久层接口
 */
public interface UserDao {
    /**
     * 根据id查询用户信息
     * @param userId
     * @return
     */
    User findById(Integer userId);
}

2.在用户的映射配置文件中配置

    <!--根据id查询用户-->
    <select id="findById" parameterType="INT" resultType="com.sunyan.domain.User">
        select * from user where id=#{uid};
    </select>

细节:
  resultType 属性:
    用于指定结果集的类型。
  parameterType 属性:
    用于指定传入参数的类型。
  sql 语句中使用#{}字符:
    它代表占位符, 相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。
    具体的数据是由#{}里面的内容决定的。
  #{}中内容的写法:
    由于数据类型是基本类型,所以此处可以随意写。

3.在测试类添加测试

   /**
    * 测试mybatis的crud操作
    */
   public class MybatisTest {
   
       private InputStream in;
       private SqlSession sqlSession;
       private UserDao userDao;
   
       @Before//用于在测试方法之前执行
       public void init() throws Exception {
           //1.读取配置文件,生成字节输入流
           in = Resources.getResourceAsStream("SqlMapConfig.xml");
           //2.获取SqlSessionFactory
           SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
           //3.获取SqlSession对象
           sqlSession = factory.openSession();
           //4.获取dao的代理对象
           userDao = sqlSession.getMapper(UserDao.class);
       }
   
       @After//用于在测试方法之后执行
       public void destroy() throws Exception {
           sqlSession.commit();
           //6.释放资源
           sqlSession.close();
           in.close();
       }
       
           /**
        * 测试查询
        */
       @Test
       public void testFindOne() {
           //5.执行查询一个方法
           User user = userDao.findById(50);
           System.out.println(user);
       }
   }

注意:
我们在实现增删改时一定要去控制事务的提交,那么在 mybatis 中如何控制事务提交呢?
可以使用:session.commit();来实现事务提交。

保存操作

1.在持久层接口中添加新增方法

   /**
    * 保存用户
    * @param user
    */
   void saveUser(User user);

2.在用户的映射配置文件中配置

    <!--保存用户-->
    <insert id="saveUser" parameterType="com.sunyan.domain.User">
        insert into user(username, address, sex,birthday)values (#{username},#{address},#{sex},#{birthday});
    </insert>

细节:
parameterType 属性:
    代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。
sql 语句中使用#{}字符:
    它代表占位符, 相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。
    具体的数据是由#{}里面的内容决定的。

{}中内容的写法:

     由于我们保存方法的参数是 一个 User 对象,此处要写 User 对象中的属性名称。
     它用的是 ognl 表达式。
ognl 表达式:
    它是 apache 提供的一种表达式语言, 全称是:
    Object Graphic Navigation Language 对象图导航语言
    它是按照一定的语法格式来获取数据的。
     语法格式就是使用 #{对象.对象}的方式
     #{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用
     getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,
    所以可以省略 user.而直接写 username。

  OGNL表达式:
	Object Graphic Navigation Language
	对象		图		导航	   语言
	
	它是通过对象的取值方法来获取数据。在写法上把get给省略了。
	比如:我们获取用户的名称
		类中的写法:user.getUsername();
		OGNL表达式写法:user.username
	mybatis中为什么能直接写username,而不用user.呢:
		因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名

3.添加测试类中的测试方法

    /**
     * 测试保存操作
     */
    @Test
    public void testSave() {
        User user = new User();
        user.setUsername("mybatis last insertid");
        user.setAddress("北京市顺义区");
        user.setSex("男");
        user.setBirthday(new Date());
        System.out.println("保存操作之前:" + user);
        //5.执行保存方法
        userDao.saveUser(user);
        System.out.println("保存操作之后:" + user);
    }

4.问题扩展:新增用户 id 的返回值

新增用户后, 同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长 auto_increment 的值返回。

    <!--保存用户-->
    <insert id="saveUser" parameterType="com.sunyan.domain.User">
        -- 配置插入操作后,获取插入数据的id
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user(username, address, sex,birthday)values (#{username},#{address},#{sex},#{birthday});
    </insert>

用户更新

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

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

2.在用户的映射配置文件中配置

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

3.加入更新的测试方法

    /**
     * 测试更新操作
     */
    @Test
    public void testUpdate() {
        User user = new User();
        user.setId(50);
        user.setUsername("mybatis update user");
        user.setAddress("北京市顺义区");
        user.setSex("女");
        user.setBirthday(new Date());

        //5.执行更新方法
        userDao.updateUser(user);
    }

用户删除

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

    /**
     * 根据id删除用户
     * @param userId
     */
    void deleteUser(Integer userId);

2.在用户的映射配置文件中配置

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

3.加入删除的测试方法

    /**
     * 测试删除
     */
    @Test
    public void testDelete() {
        //5.执行删除操作
        userDao.deleteUser(48);
    }

用户模糊查询

1.在持久层接口中添加模糊查询方法

    /**
     * 根据名称模糊查询用户信息
     * @param username
     * @return
     */
    List<User> findByName(String username);

2.在用户的映射配置文件中配置

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

3.加入模糊查询的测试方法

    /**
     * 测试模糊查询操作
     */
    @Test
    public void testFindByName() {
        //5.执行查询一个方法
        List<User> users = userDao.findByName("%王%");
        for (User user : users) {
            System.out.println(user);
        }
    }

在控制台输出的执行 SQL 语句如下:

1583135512141

我们在配置文件中没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标
识%。 配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“?”。

4.模糊查询的另一种配置方式
第一步: 修改 SQL 语句的配置,配置如下:

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

我们在上面将原来的#{}占位符,改成了${value}。注意如果用模糊查询的这种写法,那么${value}的写法就是固定的,不能写成其它名字。

第二步:测试,如下:

    /**
     * 测试模糊查询操作
     */
    @Test
    public void testFindByName() {
        //5.执行查询一个方法
//        List<User> users = userDao.findByName("%王%");
        List<User> users = userDao.findByName("王");
        for (User user : users) {
            System.out.println(user);
        }
    }

在控制台输出的执行 SQL 语句如下:1583135728291

可以发现,我们在程序代码中就不需要加入模糊查询的匹配符%了,这两种方式的实现效果是一样的,但执行的语句是不一样的。

5.#{}与${}的区别
#{}表示一个占位符号
  通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果parameterType 传输单个简单类型值, #{}括号中可以是 value 或其它名称。
${}表示拼接 sql 串
  通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值, ${}括号中只能是 value。

模糊查询的${value}源码分析
源码中指定了读取的 key 的名字就是”value”,所以我们在绑定参数时就只能叫 value 的名字。

查询使用聚合函数

1.在持久层接口中添加模糊查询方法

    /**
     * 查询总用户数
     * @return
     */
    int findTotal();

2.在用户的映射配置文件中配置

    <!--获取用户的总记录条数-->
    <select id="findTotal" resultType="int">
        select count(id) from user;
    </select>

3.加入聚合查询的测试方法

    /**
     * 查询总记录条数
     */
    @Test
    public void testFindTotal() {
        //5.执行查询一个方法
        int total = userDao.findTotal();
        System.out.println(total);
    }


原文地址:https://www.cnblogs.com/sunyanblog/p/12396139.html