Mybatis(三)各种查询功能

MyBatis的各种查询功能:

1.1查询一个实体类对象

我们先创建方法:

  * 根据id来查询用户信息
     * @param id
     * @return
     */

    User getUserById(@Param("id") Integer id );

之后我们编写映射文件:

<select id="getUserById"  resultType="User">
    select * from t_user  where id=#{id}

 我们进行编写测试类:

@Test
    public void testGetUserById(){
       SqlSession sqlSession = SqlSessionUtil.getSqlSession();
       SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
       User user = mapper.getUserById(9);
       System.out.println(user);
   }

我们运行如下所示:

1.2查询一个list集合

我们首先创建一个方法:

 /**
     * 查询所有的用户信息
     * @return
     */
    List<User> getAllUser();

之后我们编写映射文件:

<select id="getAllUser" resultType="User">
       select * from t_user
   </select>

之后我们编写测试类:

@Test
    public void testGetAllUser(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        List<User> list = mapper.getAllUser();
        list.forEach(System.out::println);

    }

 我们运行之后如下所示:

 当我们当前方法的返回值为User的时候,我们修改映射文件,,将条件删除,变为搜索全部的数据,即返回为多条数据。我们来进行查看:

<select id="getUserById"  resultType="User">
    select * from t_user 

我们运行之后如下所示:

 我们发现报的错误了,报的结果异常。我们在去调用Mapper接口中的方法的时候,我们在底层调用的是sqlSession里面一个具体的方法。比如sqlsession.selectOne.....会根据我们当前这个方法的返回值然后决定我们所使用的方法。我们当前方法的返回值为User,所以说我们当前调用的是selectOne方法。是用来查询一条数据的。是获取一个结果的,所以这个时候就会报错。

我们查询多条语句不能用实体类作为返回值。如果查询的数据是一条的话,我们可以用集合来作为返回值。

我们将映射文件修改如下所示:

 <select id="getAllUser" resultType="User">
       select * from t_user  where id=9
   </select>

 我们运行之后出现如下所示:

1.3查询单行单列的数据:

我们设置方法·如下所示:

 /**
     * 查询用户的总数量
     * @return
     */
    Integer getCount();

我们设置映射文件,如下所示:

<select id="getCount"   resultType="java.lang.Integer">
        select count(*)   from t_user
    </select>

我们设置测试类如下所示:

 @Test
    public void testGetCount(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        Integer count = mapper.getCount();
        System.out.println(count);

    }

我们运行之后如下所示:

我们发现将映射文件里面的resultType改为如下所示,仍然可以运行:

 <select id="getCount"   resultType="int">
        select count(*)   from t_user
    </select>

 我们的Mybatis给这些类型设置了别名:

MyBatis中为java中常用的类型设置了类型别名

类型:别名

Integer:Integer,int,

int:_int,_integer

Map:map

HashMap:hashmap

String:string

我们可以在下载的文件里进行查看:

 当我们查询出来的结果没有相对应得实体类,我们可以将它查询出来为map集合。以字段名为键,以字段的值为值。

实体类和map集合的区别在于实体类里面他的属性是固定的,而map集合里面没有固定的键。

Map集合得结构和咱们得实体类类型的结果很象,都是键值对。只不过实体类中是属性和属性值。

我们查询多条语句不能用实体类作为返回值。如果查询的数据是一条的话,我们可以用集合来作为返回值。

我们把一条属性值设置为map.

我们设置的方法如下所示:

 /**
     * 根据id查询用户信息为map集合
     * @param id
     * @return
     */
    
    Map<String,Object> getUserByIdToMap(@Param("id") Integer id);
    

我们编写的映射文件如下所示:

 <select id="getUserByIdToMap"  resultType="map">
        select  *from t_user where id=#{id}
    </select>

我们编写的测试方法如下所示:

 @Test
    public void testGetUserByIdToMap(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        Map<String, Object> map = mapper.getUserByIdToMap(9);
//{password=123456, gender=nan, id=9, age=23, [email protected], username=admin}
        System.out.println(map);

    }

我们运行界面如下所示:

 而其他为空的字段并不会放在map集合里面。

我们不可以将多条数据返回为一个map集合:

我们进行测试如下所示:

我们设计如下所示:

 /**
     * 查询所有的用户信息为map集合
     *
     */
    Map<String,Object> getAllUserToMap();

我们设置的映射文件如下所示:

<select id="getAllUserToMap"  resultType="map">
        select * from t_user
    </select>

我们编写的测试类如下所示:
 

 @Test
    public void testGetAllUserToMap(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        Map<String, Object> map = mapper.getAllUserToMap();
        System.out.println(map);
    }

我们运行之后如下所示:我们发现报错如下所示:

我们发现我们查出来的结果有2条,但是我们当前返回的值是一个Map集合。

我们之前通过list集合来存储我们的每一条数据转换为的实体类对象。

我们将其放在一个能存储多个map集合的List集合里面,如下所示:

我们将方法进行修改如下所示:

List<Map<String,Object>> getAllUserToMap();

我们将测试类修改如下所示:

 @Test
    public void testGetAllUserToMap(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
        List<Map<String, Object>> list = mapper.getAllUserToMap();
        System.out.println(list);
    }

我们运行界面如下所示:

  我们也可以通过map来进行获取多条数据,利用@MapKey,如下所示:

 @MapKey("id")
    Map<String,Object>   getAllUserToMap();

 测试类修改如下所示:

 @Test
    public void testGetAllUserToMap(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
       Map<String, Object> map = mapper.getAllUserToMap();
        System.out.println(map);
    }

我们进行运行之后如下所示:

 {9={password=123456, gender=nan, id=9, age=23, [email protected], username=admin}, 10={password=123456, gender=?, id=10, age=33, [email protected], username=root}}

前面的数字就是我们的id键。

我们总结如下所示:

 /**
     * 查询所有的用户信息为map集合
     *若查询的数据有多条时,并且要将每条数据给转换为map集合
     * 此时有两种解决方案:
     * 1.将mapper接口方法的返回值设置为泛型是map的list集合(用的比较多)
     * <List<Map<String,Object>>getAllUserToMap();
     * 结果:
     * [{password=123456, gender=nan, id=9, age=23, [email protected], username=admin},
     * {password=123456, gender=?, id=10, age=33, [email protected], username=root}]
     * 2.可以将每条数据转换的map集合放在一个大的Map中,但是必须要通过@MapKey注解将查询的某个字段的值作为大的Map的键
     * @MapKey("id")
     * Map<String,Object>   getAllUserToMap();
     * 结果:{9={password=123456, gender=nan, id=9, age=23, [email protected], username=admin},
     * 10={password=123456, gender=?, id=10, age=33, [email protected], username=root}}
     */
    @MapKey("id")
    List<Map<String,Object>>   getAllUserToMap();
}

特殊SQL的执行:

1.1MyBatis处理模糊查询:

我们可以通过%%来表示任意个数的任意字符。

如下所示为查询用户名中包含a的用户信息:

  

 我们通过mybatis实现如下所示:

我们设置的方法如下所示:

List<User> getUserByLike(@Param("mohu") String mohu);

我们设置的映射文件如下所示: 

 <select id="getUserByLike" resultType="User">
        select * from t_user where username like '%#{mohu}%'
    </select>

我们设置的测试类如下所示:

  @Test
    public void testGetUserByLike(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        Object mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        List<User> list = ((SpecialSQLMapper) mapper).getUserByLike("a");
        list.forEach(System.out::println);
}

我们运行之后如下所示:

我们发现我们这个时候就没法使用#{ },即占位符赋值。
1.我们发现此时出现了很多错误,当出现很多错误的时候我们从下往上看:

Caused by: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).

 如果我们在sql语句里面写'%#{mohu}%,解析之后就会用’%?%‘来进行代替。这个时候的?是属于咱们字符串的一部分的,不会被当成占位符来进行解析。所以’%#{mohu}%‘并不是占位符。

我们利用jdbc进行查看:

@Test
    public void testJDBC(){
        try {
            Class.forName("");//注册驱动
            Connection connection= DriverManager.getConnection("","","");//获取连接
            String sql="select * from t_user where username like ''%#{mohu}%";
            PreparedStatement ps=connection.prepareStatement(sql);//获取预编译对象
            //使用set方法为当前的占位符赋值
            ps.setString(1,"a");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

我们发现当我们为当前的占位符进行赋值的时候,代码报错:
 

 //使用set方法为当前的占位符赋值
          ps.setString(1,"a");

我们发现此时编译都没有通过。我们当前的?是在字符串里面的,所以说是字符串的一部分。不会被当成占位符来进行解析。

而这个时候,我们该如何去解决这样子的问题,如下所示:

我们采用${ },相当于字符串拼接:

 我们将映射文件修改如下所示:'%${mohu}%'

<select id="getUserByLike" resultType="User">
        select * from t_user where username like '%${mohu}%'
    </select>

我们继续运行之后,发现如下所示:

 2.以上为我们解决问题的第一种方式,我们来看第二种方式:

我们设置映射文件为:concat('%',#{mohu},'%')

<!--concat字符串拼接的函数,拼接好之后相当于'%a%'-->
    <select id="getUserByLike" resultType="User">
        select * from t_user where username like concat('%',#{mohu},'%')
    </select>

我们运行测试类如下所示:

 3.我们的第三种方式如下所示:

我们设置的映射文件如下所示:“%”#{mohu}"%"

 <select id="getUserByLike" resultType="User">
        select * from t_user where username like "%"#{mohu}"%"
    </select>

运行之后如下所示:

 我们解决问题的方式如下所示:

1.'%${mohu}%'

2.concat('%',#{mohu},'%')

3.“%”#{mohu}"%"

 1.2MyBatis批量删除

批量删除:通过一个sql语句来删除多条语句。

我们将表添加如下所示:

 我们将表中的2和3进行删除,我们设置的mysql语句如下所示:

DELETE FROM t_user WHERE id=1 OR id=2

 我们查看表:

我们删除成功了

我们采用另一条sql语句进行查看:

DELETE FROM t_user WHERE id IN(3,10)

 我们发现数据如下所示:

 我们继续进行添加数据,之后我们采用mybatis如何进行删除数据:

我们设置的方法如下所示:

 /**
     * 批量删除的功能
     * @param ids
     */
    void deleteMoreUser(@Param("ids") String ids);

 之后我们设置映射文件如下所示:

<delete id="deleteMoreUser"  >
        delete from t_user where id in(#{ids})
    </delete>

我们来进行查看是否这样子可以将数据进行删除,我们的测试类如下所示:

@Test
    public void testDeleteMoreUser(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        Object mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        ((SpecialSQLMapper) mapper).deleteMoreUser("1,2");

    }

我们运行之后,如下所示:

我们发现出错了。 

 delete from t_user where id in(#{ids})

因为#{ }本质上是占位符赋值,我们会自动加上单引号.被解析之后,就会变成:

 delete from t_user where id in(’1,2‘)。

但是我们的sql语句是:
 delete from t_user where id in (1,2);

我们将sql语句修改为:

<delete id="deleteMoreUser"  >
        delete from t_user where id in(${ids})
    </delete>

我们继续进行运行如下所示:’

 我们打开表之后发现如下所示:

 我们发现成功删除。

1.3MyBatis 动态设置表名:

我们设置的方法如下所示:

/**
     * 动态设置表名,查询用户信息
     * @param tableName
     * @return
     */
    List<User> getUserList(@Param("tablename") String tableName);

我们下来设置映射文件:

<select id="getUserList" resultType="User">
        select * from #{tablename}
    </select>

我们设置的测试类为:

@Test
    public void testGetUserList(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        Object mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        List<User> list = ((SpecialSQLMapper) mapper).getUserList("t_user");
        list.forEach(System.out::println);

    }

运行之后如下所示: 

 我们发现有错,表名是一定不能加单引号的,我们进行修改映射文件如下所示:

 <select id="getUserList" resultType="User">
        select * from ${tablename}
    </select>

我们再次进行运行之后如下所示:

当我们动态去设置表名的时候,我们当前只能用${ }, 

 1.4MyBatis添加功能获取自增的主键

场景模拟:

t_clazz(clazz_id,clazz_name)

t_student(student_id,student_name,student_id)

1.添加班级信息

2.获取新添加的班级的id

3.为班级分配学生,即将某学的班级id修改为新添加的班级的id

我们可以通过JDBC来实现这样子的功能。实现添加功能之后可以直接来获取它所自增的id。

 @Test
    public void testJDBC(){
        try {
            Class.forName("");//注册驱动
            Connection connection= DriverManager.getConnection("","","");//获取连接
          String sql="insert into t_user values()";
          //当前设置允许我们获取自动递增的主键
          PreparedStatement ps=connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
          //执行sql语句          
          ps.executeUpdate();
          //获取我们当前自动递增的主键,resultSet为单行单列的数据。
            ResultSet resultSet = ps.getGeneratedKeys();
            //将我们当前结果集里面的指针指向我们当前的数据
            resultSet.next();
            //当前自动递增的主键,结果集为单行单列
            //JDBC默认情况下是不允许我们来获取自动递增的主键的,我们可以设置创建预编译对象的时候进行添加。
            int id = resultSet.getInt(1);
            System.out.println(ps);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

MyBatis封装的就是JDBC,JDBC里面有,MyBatis里面也有。我们通过MyBatis进行如下所示:

我们创建的方法如下所示:

/**
     * 添加用户信息并获取自增的主键
     * @param user
     */
    void insertUser(User user);

我们创建的映射文件如下所示:

  <!--
       useGeneratedKeys:表示当前添加功能使用自增的主键
       keyProperty:将添加的数据的自增主键为实体类类型的参数的属性赋值
       将传进来的参数的某个属性id作为接收添加的数据的自增的值。
       -->
    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email})
    </insert>

我们编写的测试类如下所示:

 @Test
    public void testInsertUser(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        Object mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        User user = new User(null,"小明","123456",23,"男","[email protected]");
       ((SpecialSQLMapper) mapper).insertUser(user);
        System.out.println(user);


    }

我们运行之后如下所示:

 我们打开数据库进行查看:

我们进行刷新如下所示:

 

猜你喜欢

转载自blog.csdn.net/weixin_59448049/article/details/127338097