Mybatis基于代理Dao实现CRUD操作
使用要求:
1、持久层接口和持久层接口的映射配置必须在相同的包下
2、持久层映射配置中mapper标签的namespace属性取值必须是持久层接口的全限定类名
3、SQL语句的配置标签<select>,<insert>,<delete>,<update>的id属性必须和持久层接口的方法名相同。
持久层接口
/** * * 用户的持久层接口 */ public interface IUserDao { /** * 查询所有操作 * @return */ List<User> findAll(); /** * 保存用户 * @param user */ void saveUser(User user); /** * 更新用户 * @param user */ void updateUser(User user); /** * 根据ID删除用户 * @param userId */ void deleteUser(Integer userId); /** * 根据ID查询用户 * @param userId * @return */ User findById(Integer userId); /** * 根据名称模糊查询用户信息 * @param username * @return */ List<User> findByName(String username); /** * 查询总用户数 聚合函数 * @return */ int findTotal(); }
持久层接口对应的映射配置文件
<?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.itheima.dao.IUserDao"> <!--配置查询所有--> <select id="findAll" resultType="com.itheima.domain.User"> select * from user </select> <!--保存用户--> <insert id="saveUser" parameterType="com.itheima.domain.User"> insert into user(username,address,sex,birthday)values (#{username},#{address},#{sex},#{birthday}); </insert> <!--更新用户--> <update id="updateUser" parameterType="com.itheima.domain.User"> update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}; </update> <!--删除用户--> <!--此处dao方法中只有一个integer类型参数,只需要写清楚一个占位符就可以,占位符叫什么无所谓--> <delete id="deleteUser" parameterType="Integer"> delete from user where id=#{id}; </delete> <!--根据ID查询用户--> <select id="findById" parameterType="Integer" resultType="com.itheima.domain.User"> select * from user where id=#{id}; </select> <!--根据名称模糊查询用户信息--> <select id="findByName" parameterType="String" resultType="com.itheima.domain.User"> select * from user where username like #{username}; /*select * from user where username like '%${value}%';*/ </select> <!--使用聚合函数查询总用户数--> <select id="findTotal" resultType="int"> select count(id) from user; </select> </mapper>
测试类
package com.itheima.test; import com.itheima.dao.IUserDao; import com.itheima.domain.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 org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.InputStream; import java.util.Date; import java.util.List; public class MybatisTest { private InputStream in; private SqlSession sqlSession; private IUserDao 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(IUserDao.class); } @After//用于在测试方法执行之后执行 public void destroy()throws Exception{ //提交事务 sqlSession.commit(); //6.释放资源 sqlSession.close(); in.close(); } @Test public void testFindAll(){ //5.使用代理对象执行方法 List<User> users = userDao.findAll(); for(User user : users){ System.out.println(user); } } /** * 测试保存操作 */ @Test public void testSaveUser(){ User user =new User (); user.setAddress ("QingDao"); user.setBirthday (new Date ()); user.setSex ("m"); user.setUsername ("MKL"); userDao.saveUser (user); } /** * 测试更新操作 */ @Test public void testUpdateUser(){ User user =new User (); user.setId (59); user.setAddress ("HuangDao"); user.setBirthday (new Date ()); user.setSex ("男"); user.setUsername ("MKL"); userDao.updateUser (user); } /** * 测试根据ID进行删除 */ @Test public void testDeleteUser(){ userDao.deleteUser (43); } /** * 测试根据ID查询用户 */ @Test public void testFindById(){ User user=userDao.findById (59); System.out.println (user); } /** * 测试根据名称模糊查询用户信息 */ @Test public void testFindByName(){ List<User> users = userDao.findByName ("%王%"); //List<User> users = userDao.findByName ("王"); System.out.println (users); } /** *使用聚合函数查询总用户数 */ @Test public void testFindTotal(){ System.out.println (userDao.findTotal ()); } }
问题扩展:进行模糊查询时两种方式的区别
第一种方式 PreparedStatement的参数占位符
第二种方式: Statement对象的字符串拼接SQL
问题扩展:新增用户id的返回值
新增用户后,同时还要返回当前新增用户的id值,因为id是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长auto_increment的值返回。
keyProperty 对应的属性名称
<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>
Mybatis的参数深入 传递pojo包装对象
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。 Pojo类中包含pojo。
需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中。
编写QueryVo
package com.itheima.domain; import java.io.Serializable; /** * Created by IDEA * User:MKL7 * Date:2019/4/20 * Time:15:45 */ /** * 查询条件对象对象 */ public class QueryVo implements Serializable { private User user; public User getUser () { return user; } public void setUser (User user) { this.user = user; } }
编写持久层接口
/** * 根据QueryVo中的条件 查询用户信息 * @param queryVo * @return */ List<User> findByVo(QueryVo queryVo);
持久层接口的映射文件
<!--根据QueryVo中的条件查询用户信息--> <select id="findByVo" resultType="com.itheima.domain.User" parameterType="com.itheima.domain.QueryVo"> select * from user where username like #{user.username}; </select>
测试包装类作为参数
/** * 测试根据QueryVo 查询用户信息 */ @Test public void testFindByVo () { User user = new User (); user.setUsername ("%王%"); QueryVo queryVo = new QueryVo (); queryVo.setUser (user); List<User> users=userDao.findByVo (queryVo); System.out.println (users); }