Mybatis学习day_03mybatisCRUD以及Dao层开发配置文件配置

Mybatis的CRUD

代理对象(dao)的执行过程(跟踪源码图)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aOlIQqbq-1569984269217)(./images/非常重要的一张图-分析代理dao的执行过程.png)]

//动态代理 
public class MapperProxyFactory<T> {
    
    protected T newInstance(MapperProxy<T> mapperProxy){
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface }, mapperProxy) //第一个参数为类加载器,第二个参数为实现接口数组,第三个参数为如何代理,这里重点关注第三个参数(后面肯定是要反射了)
    }
}
编写代码实现增删改查功能
  • IUserDao接口
//用户的持久层接口
public interface IUserDao {

    //查询所有用户
    List<User> findAll();

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

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

    //根据Id删除用户
    void deleteUser(Integer userId);

    //根据id查询用户信息
    User findById(Integer userId);

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

    //根据queryVo中的条件查询用户
    List<User> findUserByVo(QueryVo vo);
}
  • 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.itheima.dao.IUserDao">

    <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
    <resultMap id="userMap" type="uSeR">
        <!-- 主键字段的对应 -->
        <id property="userId" column="id"></id>
        <!--非主键字段的对应-->
        <result property="userName" column="username"></result>
        <result property="userAddress" column="address"></result>
        <result property="userSex" column="sex"></result>
        <result property="userBirthday" column="birthday"></result>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userMap">
        <!--select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user;-->
        select * from user;
    </select>

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

    <!-- 更新用户 -->
    <update id="updateUser" parameterType="USER">
        update user set username=#{userName},address=#{userAddress},sex=#{userAex},birthday=#{userBirthday} where id=#{userId}
    </update>

    <!-- 删除用户-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{uid}
    </delete>
    
    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultMap="userMap">
        select * from user where id = #{uid}
    </select>

    <!-- 根据名称模糊查询 -->
    <select id="findByName" parameterType="string" resultMap="userMap">
          select * from user where username like #{name}
        <!-- select * from user where username like '%${value}%'-->
   </select>

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

    <!-- 根据queryVo的条件查询用户 -->
    <select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultMap="userMap">
        select * from user where username like #{user.username}
    </select>
</mapper>

OGNL表达式:

  • Object Graphic Navigation Language(对象 图 导航 语言)
  • 它是通过对象的取值方法来获取数据,在写法上把get给省略了。比如:获取用户名称 类中写法:user.getUsername() OGNL:user.username
  • mybatis在parameterType中已经提供了属性所属的类,所以不需要写对象名,可以直接写属性名

Mybatis编写Dao层开发(断点调试,跟踪源码)

编写代码步骤分析
  1. SqlSessionFactoryBuilder接受SqlMapConfig.xml文件流,构建出SqlSessionFactory对象
  2. SqlSessionFactory读取SqlMapConfig.xml中连接数据库和mapper映射信息,用来生产出真正操作数据库的SqlSession对象
  3. SqlSession对象有两大作用:(1)生成接口代理对象 (2)定义通用增删改查方法。 接下来无论使用哪个分支,除了连接数据库信息,还需要得到sql语句
  4. 作用:第一点是作用(1)第二点作用(2)
    1. 在SqlSessionImpl对象的getMapper()方法中分两步来实现。第一:先用SqlSessionFactory读取的数据库连接信息创建Connection对象。第二:通过jdk代理模式创建出代理对象作为getMapper()方法返回值,这里主要工作是在创建代理对象时第三个参数处理类里面得到sql语句,执行对应CRUD操作
    2. 在SqlSessionImpl对象中提供selectList()方法,当然实际mybatis框架中还有selectOne,insert等方法,这些方法内也分两步。第一:用SqlSessionFactory读取的数据库连接信息创建出jdbc的COnnection对象,第二:直接得到sql语句,使用jdk的Connection对象进行对应的CRUD操作
  5. 封装结果集:无论使用分支一生成代理对象,还是直接使用分支二提供的通用CRUD方法,我们都要对返回的数据库结果集进行封装,编程java对象返回给调用者。所以我们必须要知道调用者所需要的返回类型

总结:通过以上流程不难看出,无论是让mybatis帮我们创建代理对象还是直接使用mybatis提供的CRUD方法,其本质都是JDBC的Connection对象,执行对应的sql语句,最终封装结果集。只是注解和xml配置文件两种开发模式在传递sql语句和返回值类型的方式上有所差异而已。如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dyvwTi8X-1569984269218)(./images/注解方式.png)]

示例代码
/**
 * MyvatisDao层开发,用户接口实现类
 * @author eric
 * @Company http://www.ithiema.com
 */
public class UserDaoImpl implements IUserDao {

    private SqlSessionFactory factory;

    public UserDaoImpl(SqlSessionFactory factory){
        this.factory = factory;
    }

    @Override
    public List<User> findAll() {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用SqlSession中的方法,实现查询列表
        List<User> users = session.selectList("com.itheima.dao.IUserDao.findAll");//参数就是能获取配置信息的key
        //3.释放资源
        session.close();
        return users;
    }

    @Override
    public void saveUser(User user) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用方法实现保存
        session.insert("com.itheima.dao.IUserDao.saveUser",user);
        //3.提交事务
        session.commit();
        //4.释放资源
        session.close();
    }

    @Override
    public void updateUser(User user) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用方法实现更新
        session.update("com.itheima.dao.IUserDao.updateUser",user);
        //3.提交事务
        session.commit();
        //4.释放资源
        session.close();
    }

    @Override
    public void deleteUser(Integer userId) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用方法实现更新
        session.update("com.itheima.dao.IUserDao.deleteUser",userId);
        //3.提交事务
        session.commit();
        //4.释放资源
        session.close();
    }

    @Override
    public User findById(Integer userId) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用SqlSession中的方法,实现查询一个
        User user = session.selectOne("com.itheima.dao.IUserDao.findById",userId);
        //3.释放资源
        session.close();
        return user;
    }

    @Override
    public int findTotal() {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用SqlSession中的方法,实现查询一个
        Integer count = session.selectOne("com.itheima.dao.IUserDao.findTotal");
        //3.释放资源
        session.close();
        return count;
    }
}
//----------------------------
/**
 * 测试mybatis的crud操作
 */
public class MybatisTest {

    private InputStream in;
    private IUserDao userDao;

    @Before//用于在测试方法执行之前执行
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.使用工厂对象,创建dao对象
        userDao = new UserDaoImpl(factory);
    }

    @After//用于在测试方法执行之后执行
    public void destroy()throws Exception{
        //6.释放资源
        in.close();
    }

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll(){
        //5.执行查询所有方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }

    }

}
Mybatis执行过程(CRUD)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ja2UHv4K-1569984269218)(./images/非常重要的一张图-分析编写dao实现类Mybatis的执行过程.png)]

PreparedStatement对象它的执行方法。
excute:它能执行CURD中的任意一种语句,它的返回值是boolean类型,表示是否有结果集,有是true,没有false。
excuteUpdate:它只能执行CUD语句,查询语句无法执行。它的返回值是影响数据库记录的行数
excuteQuery:它只能执行SELECT语句,无法执行增删改,执行结果是封装的结果集ResultSet对象


配置文件(代理dao)

  • 配置文件jdbcConfig.properties

    <!-- 配置文件名,存在rousource目录下 -->
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/eesy_mybatis
    jdbc.username=root
    jdbc.password=1234
    
  • SqlMapConfig.xml中的配置properties

    • 可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
    • resource属性: 常用的。用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
    • url属性:是要求按照Url的写法来写地址。
    • URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
    • 它的写法:http://localhost:8080/mybatisserver/demo1Servlet

      协议 主机 端口 URI
    • URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
    <!-- 示例代码 -->
    <properties url="file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.properties">
        <!-- <property name="driver" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"></property>
        <property name="username" value="root"></property>
        <property name="password" value="1234"></property>-->
    </properties>
    
    <!--配置环境-->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"></transactionManager>
    
            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    
  • 使用typeAliases配置别名

    • ypeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名就不再区分大小写

      <typeAlias type="com.my.domain.User" alias="user"></typeAlias>
    • 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写

      <package name="com.my.domain"></package>
    • package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了
      <!-- 配置映射文件的位置 -->
      <mappers>
          <!--<mapper resource="com/itheima/dao/IUserDao.xml"></mapper>-->
          <!-- package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了 -->
          <package name="com.my.dao"></package>
      </mappers>
      
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值