Mybatis主要知识点

Mybatis的基础环境搭建

  • [1] 创建一个不需要任何骨架的maven项目
  • [2] 在pom中导入需要的jar包坐标
  • [3] 在resources中创建一个SqlConFig.xml主配置文件
    在这里插入图片描述

第一个value后面写的是想要连接的数据库的驱动
第二个value后面写的想要连接的数据库名称
第三第四行是连接数据库的用户名和密码

在这里插入图片描述
mapper标签中设置想要加载的接口子配置文件

  • [4] 在resources资源目录下创建一个mapper文件夹,文件夹存放各个接口的配置文件
    在这里插入图片描述
    mapper中写入加载的接口路径
  • [5] 将log4j配置文件导入resources资源目录下

框架中的几个主要对象

            //将主配置文件以流的形式加载到内存中
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //得到一个工厂生产者对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            //生产一个数据库执行对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
			//用动态代理的方式将接口加载
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  • [1] SqlSession对象
    回顾原生jdbc操作:加载数据库驱动,创建Connection链接,得到预编译的操作对象,执行数据库操作得到结果集ResultSet,处理器结果集得到User对象,释放资源。
    Mybatis框架对以上操作进行了封装。 Mybatis真正操作数据库的对象就是SqlSession。
    由于Connection对象线程不安全,所以SqlSession也线程不安全。
    由于SqlSession线程不安全,所有需要反复的创建和销毁。 由于对象要不断的创建和销毁,要用工厂模式。
  • [2] SqlSessionFactory对象
    专门负责创建SqlSession对象。
  • [3] SqlSessionFactoryBuilder对象
    把配置文件中的数据解析出来,并放到一个对象中,供SqlSessionFactory使用。
  • [4] Resources对象
    把配置文件变成流。

使用mybatis框架映射方式进行单表的增删改

    //接口
public interface UserMapper {

    //添加一条用户数据信息到数据库中
    public void saveUser(User user);

    //根据id更新一条用户的信息
    public void updateUser(User user);

    //根据用户id删除一条数据库中的记录
    public void deleteUser(Integer id);
}
      //测试方法
      //向数据库添加一条新的记录
    @Test
    public void saveUser(){
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //创建一个实例对象
        User user = new User();
        user.setUsername("舒克");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("黑马程序员");
        mapper.saveUser(user);
    }
      //根据用户id更改用户信息
    @Test
    public void updateUser(){
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //创建一个实例对象
        User user = new User();
        user.setUsername("贝塔");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("黑马程序员");
        user.setId(54);
        mapper.updateUser(user);
    }


    //根据用户id删除一条数据库中的记录
    @Test
    public void deleteUser(){
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //创建一个实例对象
        User user = new User();
        mapper.deleteUser(54);
    }
	<!-- 配置文件 -->
	    <!-- namespace的当前mapper的唯一标识,一个类对象对应一个唯一的标识 -->
    <!--
    insert 标签是用来做添加操作的
    id 是当前想要执行的sql语句的唯一标识
    parameterType 是当前参数的类型
    #{} 是占位符,完全等同于?号占位符
    如果想要传递的参数是对象类型的,#{}中写的是对象的属性名
    -->
    
   <!-- 添加一条有用户信息到数据库中 -->
    <insert id="saveUser" parameterType="user">
        insert into user (username,birthday,sex,address)
        values(#{username},#{birthday},#{sex},#{address})
    </insert>

    <!-- 根据id更新一条数据库中的用户数据信息 -->
    <update id="updateUser" parameterType="user">
        update user set username=#{username},
                          birthday=#{birthday},
                          sex=#{sex},
                          address=#{address}
                          where id = #{id}
    </update>

    <!-- 根据用户id删除一条数据库中的记录 -->
    <delete id="deleteUser" parameterType="int">
        delete from user where id=#{id}
    </delete>

总结: 从以上三条单表的增删查改中可以发现,执行sql语句的标签中,id属性后写的是映射的接口中的抽象方法名称,parameterType属性后写的是接口抽象方法向数据库传递的参数(简单来说也就是占位符所代表的数据类型)

使用mybatis框架映射方式进行单表的数据查询

    //接口
    //查询用户表中的所有数据
    public List<User> findAll();
    //根据id查询对应的用户信息,列名使用别名
    public User findById(Integer id);
//测试类
  //查询用户表中的所有数据
   @Test
   public void findAll() {
       //用动态代理的方式将接口加载
       UserMapper mapper = sqlSession.getMapper(UserMapper.class);
       //创建一个实例对象
       User user = new User();
       List<User> all = mapper.findAll();
       System.out.println(all);
   }


   //根据id查询对应的用户信息,列名使用别名
   @Test
   public void findById() {
       //用动态代理的方式将接口加载
       UserMapper mapper = sqlSession.getMapper(UserMapper.class);
       User byId = mapper.findById(53);
       System.out.println(byId);
   }
<!-- 配置文件 -->
<!-- 查询用户表中的所有数据 -->
   <select id="findAll" resultType="user">
       select * from user
   </select>

   <!-- 根据id查询对应的用户信息,列名使用别名 -->
   <!-- id为自己制定的名称(跟下面select标签中的resultMap属性相对应)
    type是返回的map集合中封装的对象名称 -->
   <resultMap id="userMap" type="user">
       <!-- id标签中的property为主键名称,只是一个规范,也可以都写成result标签,
       column标签中写入的是给对应列名起得别名-->
      <id property="id" column="_id"/>
       <result property="username" column="_username"/>
       <result property="birthday" column="_birthday"/>
       <result property="sex" column="_sex"/>
       <result property="address" column="_address"/>
   </resultMap>
   <select id="findById" parameterType="int" resultMap="userMap">
       select id _id,username _username,birthday _birthday,sex _sex,address _address from user where id=#{id}
   </select>

**总结:**当执行查询操作的时候,可以使用resultType属性可以使用resultMap属性,这两个属性后填写的都是查询出来对象的名称.但是使用resultType属性必须要保证查询列名与数据库表中列名的一致性.而resultMap可以通过标签给查询列名设置别名,在resultMap标签中的id属性与select标签中的sersltMap属性是对应的.

使用mybatis框架映射方式进行有多个参数的单表数据查询

  //接口
  //根据id和用户名查询数据库中的用户信息
    public User findByIdAndUsername(Integer id,String username);
  //测试方法
    //根据id和用户名查询数据库中的用户信息
    @Test
    public void findByIdAndUsername() {
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //执行查询语句并返回结果
        User u = mapper.findByIdAndUsername(53, "乐");
        System.out.println(u);
    }
  //映射文件
  <!-- 根据id和用户名查询数据库中的用户信息 -->
    <select id="findByIdAndUsername" resultType="user">
        select * from user where id=#{id} and username=#{username}
    </select>

尝试以上返回后idea却给出了报错信息
在这里插入图片描述根据报错信息,我们尝试写入另外的两种形式
在这里插入图片描述在这里插入图片描述 在这里插入图片描述成功获取到了用户的信息

实在不想用以上的方式,又想用占位符可以采取使用Param注解的方式

   //接口
   //使用@Param注解的方式根据id和用户名查询数据库中的用户信息
    public User findByIdAndUsernameParam(@Param("id") Integer id, @Param("username") String username);
  <!-- 配置文件 -->
   <!-- 使用@Param注解的方式根据id和用户名查询数据库中的用户信息 -->
    <select id="findByIdAndUsernameParam" resultType="user">
        select * from user where id=#{id} and username=#{username}
    </select>
    //测试类
    //使用@Param注解的方式根据id和用户名查询数据库中的用户信息
    @Test
    public void findByIdAndUsernameParam() {
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //执行查询语句并返回结果
        User u = mapper.findByIdAndUsernameParam(46, "老王");
        System.out.println(u);
    }

使用mybatis框架映射方式进行单表模糊查询(常用的两种方式)

    //接口
    //模糊查询(方式一)
    public List<User> findByUsername(String username);

    //模糊查询(方式二)
    public List<User> findByUsernameTwo(String username);
 <!-- 模糊查询 -->
    <select id="findByUsername" parameterType="String" resultType="user">
        select * from user where username like #{username}
    </select>

    <!-- 模糊查询 -->
    <select id="findByUsernameTwo" parameterType="String" resultType="user">
        select * from user where username like '%${value}%'
    </select>
  //模糊查询(方式一)
    @Test
    public void findByUsername() {
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //执行查询语句并返回结果
        List<User> list = mapper.findByUsername("老王");
        System.out.println(list);
    }

    //模糊查询(方式二)
    @Test
    public void findByUsernameTwo() {
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //执行查询语句并返回结果
        List<User> list = mapper.findByUsernameTwo("老王");
        System.out.println(list);
    }

获取新添加数据的主键值

使用场景: 级联保存,保存主表数据的同时保存从表数据,从表是包含外键的表,外键来自于主表的主键,这时就需在主表数据保存完成后,得到当前新增数据的主键值。
通过我们第一次使用的添加方法查看是否能获取到主键的值

    @Test
    public void saveUser() {
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //创建一个实例对象
        User user = new User();
        user.setUsername("舒克");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("黑马程序员");
        mapper.saveUser(user);
        System.out.println("---------"+user.getId());
    }

在这里插入图片描述我们可以看见获取到的值为空

通过修改映射文件,尝试是否能获取到新添加数据在表中的主键值

 <!-- 添加一条有用户信息到数据库中 -->
 <!-- 其中的useGeneratedKeys="true" 表示在执行完添加操作以后,获取到新添加数据的主键值
 		keyProperty="id" 表示 当获取新增数据的主键值以后赋值给对象中的那个属性
  -->
    <insert id="saveUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
        insert into user (username,birthday,sex,address)
        values(#{username},#{birthday},#{sex},#{address})
    </insert>

在修改完配置文件一会,再次运行,尝试是否可以获取到新增数据在表中的主键值
在这里插入图片描述再次运行后我们发现可以成功获取值,可是发现了一个新的问题,在Oracle数据库中主键是没有自增的
功能的,所以这种解决方式并不能保证代码的通用性
在这里插入图片描述

动态sql之if判断

   //接口
   //根据用户名获取id进行数据查询
    public List<User> findByUsernameOrId(User user);
   <!-- 根据用户名获取id进行数据查询 -->
    <!-- where标签表示where关键字,并且会在需要的时候自动去掉and
         if标签表示java中的if关键字,用于判断条件,相当于java中的多重if
     -->
    <select id="findByUsernameOrId" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="id != null">
                and id=#{id}
            </if>
            <if test="username != null and username != ''">
                and username=#{username}
            </if>
        </where>
    </select>  
     //测试方法
     //根据用户名获取id进行数据查询
    @Test
    public void findByUsernameOrId(){
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUsername("老王");
        //执行查询语句并返回结果
        List<User> list = mapper.findByUsernameOrId(user);
        System.out.println(list);
    }

使用mybatis框架映射方式进行单表查询是一次传递多个参数

 //接口
 //一次查询多个指定id的用户数据
 public List<User> findByManyId(@Param("ids") List<Integer> ids);   
   <!-- 配置文件 -->
   <!-- 一次查询多个指定id的用户数据 -->
    <select id="findByManyId" parameterType="int" resultType="user">
        select * from user
        <where>
        <foreach collection="ids" item="id" open="id IN( " separator="," close=")" >
            #{id}
        </foreach>
        </where>
    </select>        
```java
   //测试方法  
    //一次查询多个指定id的用户数据
    @Test
    public void findByManyId(){
        //用动态代理的方式将接口加载
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<Integer> ids = new ArrayList<Integer>();
        ids.add(51);
        ids.add(52);
        ids.add(53);
        List<User> byManyId = mapper.findByManyId(ids);
        System.out.println(byManyId);
    }

使用mybatis框架映射方式进行双表关联查询

   //接口
 //双表关联查询所有账户下的所有用户信息
    public List<Account> findAllTwo();
	//配置文件
	<!-- <resultMap id="accountMap" type="account"> 不推荐写法
       <id property="id" column="id"/>
       <result property="money" column="money"/>
       <result property="user.id" column="uid"/>
       <result property="user.username" column="username"/>
       <result property="user.birthday" column="birthday"/>
       <result property="user.sex" column="sex"/>
       <result property="user.address" column="address"/>
   </resultMap>-->

   <!-- 推荐写法 -->
   <resultMap id="accountMap" type="account">
   <id property="id" column="id"/>
   <result property="money" column="money"/>
       <association property="user" javaType="user">
           <result property="id" column="uid"/>
           <result property="username" column="username"/>
           <result property="birthday" column="birthday"/>
           <result property="sex" column="sex"/>
           <result property="address" column="address"/>
       </association>
   </resultMap>
   <select id="findAllTwo" resultMap="accountMap">
       select * from account a left join user u on a.uid=u.id
   </select>
//测试方法
 //双表关联查询所有账户下的所有用户信息
    @Test
    public void  findAllTwo(){
        //用动态代理的方式将接口加载
        AccountMapper mapper = sqlSession.getMapper(AccountMapper.class);
        List<Account> allTwo = mapper.findAllTwo();
        System.out.println(allTwo);
    }

使用mybatis框架嵌套查询<重点>☆☆☆

概念:一个查询中嵌套了另外一个查询,优势是把原本一次多表联查的操作,拆分成多个单表查询。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值