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>
我们运行之后出现如下所示:
若sql语句查询的结果为多条时,一定不能以实体类类型作为方法的返回值,否则会抛出异常TooManyResultsException
若sql语句查询的结果为一条时,此时可以使用实体类类型或list集合类型作为方法的返回值。
1.3查询单行单列的数据:
我们设置方法·如下所示:
/** * 查询用户的总数量 * @return */ Integer getCount();
我们设置映射文件,如下所示:
<!--count(*)可以是*,可以是1/2等,但不可以是字段--> <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=123452@qq.com, username=admin} System.out.println(map); }
采用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=123452@qq.com, username=admin},
10={password=123456, gender=?, id=10, age=33, email=123@qq.com, username=root}}
前面的数字就是我们的id键。
我们总结如下所示:
/** * 查询所有的用户信息为map集合 *若查询的数据有多条时,并且要将每条数据给转换为map集合 * 此时有两种解决方案: * 1.将mapper接口方法的返回值设置为泛型是map的list集合(用的比较多) * <List<Map<String,Object>>getAllUserToMap(); * 结果: * [{password=123456, gender=nan, id=9, age=23, email=123452@qq.com, username=admin}, * {password=123456, gender=?, id=10, age=33, email=123@qq.com, username=root}] * 2.可以将每条数据转换的map集合放在一个大的Map中,但是必须要通过@MapKey注解将查询的某个字段的值作为大的Map的键 * @MapKey("id") * Map<String,Object> getAllUserToMap(); * 结果:{9={password=123456, gender=nan, id=9, age=23, email=123452@qq.com, username=admin}, * 10={password=123456, gender=?, id=10, age=33, email=123@qq.com, username=root}} */ @MapKey("id") List<Map<String,Object>> getAllUserToMap(); }
特殊SQL的执行:
1.1MyBatis处理模糊查询:
1.'%${mohu}%'
2.concat('%',#{mohu},'%')
3.“%”#{mohu}"%"
模糊查询使用关键字Like.
我们可以通过%%来表示任意个数的任意字符。
如下所示为查询用户名中包含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批量删除:DELETE FROM t_user WHERE id IN(3,10)
DELETE FROM t_user WHERE id=1 OR id=2,${}
批量删除:通过一个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:添加功能获取自增的主键:
useGeneratedKeys:表示当前添加功能使用自增的主键
keyProperty:将添加的数据的自增主键为实体类类型的参数的属性赋值将传进来的参数的某个属性id作为接收添加的数据的自增的值。
场景模拟:
t_clazz(clazz_id,clazz_name)
t_student(student_id,student_name,student_id)
1.添加班级信息
2.获取新添加的班级的id
3.为班级分配学生,即将某学生的班级id修改为新添加的班级的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,"男","123@qq.com"); ((SpecialSQLMapper) mapper).insertUser(user); System.out.println(user); }
我们运行之后如下所示:
我们打开数据库进行查看:
我们进行刷新如下所示: