mybatis学习——基于代理 Dao 实现 CRUD 操作

使用要求: 

  1、持久层接口和持久层接口的映射配置必须在相同的包下 

  2、持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名 

  3、SQL 语句的配置标签<select>,<insert>,<delete>,<update>的 id 属性必须和持久层接口的 方法名相同。

在持久层接口中添加 findById 、saveUser、updateUser、deleteUser、findByName、findTotal方法

public interface IUserDao {
    /**
     * 根据id查询
     */
    User findById(Integer uid);
    /**
     * 保存用户
     */
    void saveUser(User user);
    /**
     * 更新用户
     */
    void updateUser(User user);
    /**
     * 根据id删除用户
     */
    void deleteUser(Integer uid);//这里的返回值类型是void还是int,影响不大,同上
    /**
     * 根据名称模糊查询
     */
    List<User> findByName(String username);
    /**
     * 查询总记录条数
     */
    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.churujianghudezai.dao.IUserDao">
    <!--这里的id值直接和接口里的方法名对应-->
    <!--根据id查询-->
    <select id="findById" parameterType="int" resultType="com.churujianghudezai.domain.User">
        select * from user where id = #{uid}
    </select>

    <!--保存用户,并返回保存后该用户对应的id-->
    <insert id="saveUser" parameterType="com.churujianghudezai.domain.User">
        <!--配置时保存获取插入的id
         AFTER:此语句在插入语句之后执行 (可不写)
         keyColumn="id":keyColumn用于指定数据库表user中的主键(可不写)
         keyProperty="id": 此语句返回值要传递给当前方法参数中的id属性 (com.churujianghudezai.domain.User的id属性)(不可省)
         resultType=“int”: 此语句执行后的返回类型是 int
         keyProperty和resultType必不可少,且要相互对应才行-->
        <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user(username,birthday,sex,address)values(#{username},#{birthday},#{sex},#{address})
    </insert>

    <!--更新用户,这里以更新用户名为例-->
    <update id="updateUser" parameterType="com.churujianghudezai.domain.User">
        update user set username=#{username} where id=#{id}
    </update>

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

    <!--根据名称模糊查询-->
    <select id="findByName" resultType="com.churujianghudezai.domain.User" parameterType="String">
        select * from user where username like #{username}/* 此处也可以写成 like '%${value}%' */
    </select>

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

</mapper>

细节: 

resultType 属性:  

  用于指定结果集的类型。 当结果类型为实体类时,这就要求该类中的属性名与数据库表中字段名保持一致(可以不区分大小写)(请看下一章博客内容:mybatis参数深入)

parameterType 属性:

  用于指定传入参数的类型,需要注意的是:

   1.若参数类型写成User类,那么该参数名得要写成该类中对应的属性名,如:

         parameterType="com.churujianghudezai.domain.User"      update user set username=#{username} where id=#{id} 这里id不能写成userid、uid,username不能写成name等

    它用的是 ognl 表达式。 

    ognl 表达式:它是 apache 提供的一种表达式语言,全称是:Object Graphic Navigation Language  对象图导航语言   它是按照一定的语法格式来获取数据的。  

    (语法格式就是使用  #{对象.对象}的方式 :#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用 getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user. 而直接写 username。)

   2.若参数类型是基本数据类型或String,则参数名可以随意起,如:

    parameterType="int"      select * from user where id = #{uid}   这里参数类型定义的是int,不是User,所以该参数名可以随便起,如userid等

    (因为这条是查询语句,有返回结果,且该结果类型为user类,这就要求该类中属性名与数据表中字段名一致)

sql 语句中使用#{}字符:  

  它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。 

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

  ${}表示拼接 sql 串  通过${}可以将 parameterType 传入的内容拼接在 sql中且不进行 jdbc 类型转换, ${}可以接收简 单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。

在测试类添加测试

public class MybatisCRUDTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao userDao;

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

    @Test
    public void testSaveUser(){
        User user = new User();
        user.setUsername("赵本山");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setAddress("辽宁铁岭");
        System.out.println("保存操作之前:"+user.getId());
        userDao.saveUser(user);
        //在dao操作完成后,直接调用getId()就可获得用户保存后对应的自增id
        System.out.println("保存操作完成,获得的id为"+user.getId());
    }

    @Test
    public void testUpdateUser(){
        User user = userDao.findById(59);
        user.setUsername("小飞侠");
        userDao.updateUser(user);
        user = userDao.findById(59);
        System.out.println(user);
    }

    @Test
    public void testDeleteUser(){
        userDao.deleteUser(58);
    }

    @Test
    public void testFindByName(){
        /*xml文件中使用%${value}%方式配置时,这里的参数只要写成 “王” 即可*/
        List<User> users = userDao.findByName("%王%");
        for (User user:users){
            System.out.println(user);
        }
    }

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

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

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

Mybatis 与 JDBC 编程的比较

1.数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

  解决:  在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。

2.Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。

   解决:  将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。

3.向sql语句传参数麻烦,因为sql语句的where 条件不一定,可能多也可能少,占位符需要和参数对应。

  解决:  Mybatis自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的 类型。

4.对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对 象解析比较方便。

  解决:  Mybatis自动将 sql执行结果映射至 java 对象,通过statement中的resultType 定义输出结果的 类型。

 

 

posted @ 2020-05-11 14:07  大盘鸡嘹咋咧  阅读(124)  评论(0编辑  收藏  举报