当前位置: 首页 > news >正文

Mybatis框架基础

目录

一、单元测试

二、增删改查

1.向数据库增添数据

2.删除数据库数据

3.修改数据库数据

4.查询返回简单基本类型

5.返回多个数据

三、关联查询

1.多表查询

(1)准备工作

(2)多表查询

        标签

        标签

2.嵌套查询

四、动态sql

1.if元素

2.where元素

3.trim元素

4.choose元素

5.set元素

6.foreach 元素


        在数据库创建admin管理员表为例

一、单元测试

        程序员一般会使用的测试方法,是以方法为单位进行测试,这里需要使用junit组件实现。

在pom.xml文件中加入以下代码。

<!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>provided</scope></dependency>

这样我们就可以在方法外加上@Test注解标签直接对该方法实现运行测试,如图

二、增删改查

1.向数据库增添数据

@Testpublic void insert(){Admin admin = new Admin();//数据封装到对象中admin.setAccount("aaa");admin.setPassword("132");admin.setGender("男");SqlSession sqlSession = MyBatisUtil.getSqlSession();AdminDao adminDao = sqlSession.getMapper(AdminDao.class);adminDao.insertAdmin(admin);//拿主键System.out.println(admin.getId());sqlSession.commit();//提交数据库事务,程序无异常才提交事务,执行sql。新增修改删除完成后都需手动提交事务
//void insertAdmin(Admin admin);接口中的方法sqlSession.close();/*数据库事物:是数据库的一种管理机制,对一次连接数据库过程进行管理例如:sql1其它代码(有异常)sql2提交事务(一次执行完所有sql,但是因为在其它代码部分有异常,会终止提交事务,因此sql都不会执行)*/}

        映射文件相应标签 

    <!--useGeneratedKeys="返回自增主键"keyProperty="接收主键属性"keyColumn="主键列"--><insert id="insertAdmin" parameterType="Admin" useGeneratedKeys="true" keyProperty="id" keyColumn="id">insert into admin(account,password,gender)values (#{account},#{password},#{gender})</insert>

2.删除数据库数据

        删除id为4的管理员信息

@Testpublic void delete(){SqlSession sqlSession = MyBatisUtil.getSqlSession();AdminDao adminDao = sqlSession.getMapper(AdminDao.class);adminDao.deleteAdmin(4);sqlSession.commit();sqlSession.close();}//void deleteAdmin(int id);接口中的方法

        映射文件相应标签 

<delete id="deleteAdmin" parameterType="int">delete from admin where id = #{id}</delete>

3.修改数据库数据

        修改id为3的管理员信息

@Testpublic void update(){Admin admin = new Admin();admin.setId(3);admin.setAccount("ccc");admin.setPassword("123");SqlSession sqlSession = MyBatisUtil.getSqlSession();AdminDao adminDao = sqlSession.getMapper(AdminDao.class);adminDao.updateAdmin(admin);sqlSession.commit();sqlSession.close();}//void updateAdmin(Admin admin);接口中的方法

       映射文件相应标签 

<update id="updateAdmin" parameterType="Admin">update admin set account = #{account},password=#{password} where id = #{id}</update>

4.查询返回简单基本类型

        单表查询,返回的结果mybatis自动将结果映射到java对象中,但必须要表中列名与类中属性名一致!

注:MySQL中对于两个单词采用A_B链接,但是java使用驼峰表示findAdmin,因此这里我们可以在mybatis.xml配置文件中<settings>标签中加入如下代码即可相互转换,还不影响单表查询因为属性名与列名不一致引起的查询失效。

<setting name="mapUnderscoreToCamelCase" value="true"/> 

@Testpublic void find1(){SqlSession sqlSession = MyBatisUtil.getSqlSession();AdminDao adminDao = sqlSession.getMapper(AdminDao.class);int count = adminDao.findAdminCount();int id = adminDao.findAdminId("account");sqlSession.commit();sqlSession.close();}//int findAdminCount();接口中的方法

       映射文件相应标签 

<!--单表查询,返回的结果mybatis自动将结果映射到java对象中,但必须要表中列名与类中属性名一致--><!--java.lang.Integer,全类名,这里我们用别名integer代替--><select id="findAdminCount" resultType="integer">select count(*) from admin</select>

5.返回多个数据

@Testpublic void find2(){SqlSession sqlSession = MyBatisUtil.getSqlSession();AdminDao adminDao = sqlSession.getMapper(AdminDao.class);List<Admin> admins = adminDao.findAdmins("password");sqlSession.commit();sqlSession.close();}//List<Admin> findAdmins(@Param("orderColumn") String orderColumn);接口方法

        映射文件相应标签 

    <select id="findAdmins" resultType="Admin" parameterType="string">select ${orderColumn} from admin order by ${orderColumn} desc</select>

三、关联查询

1.多表查询

(1)准备工作

        我们在数据库中再创建两张表student和major

在IDEA分别写出相应的类、接口、映射文件,记得在mybatis.xml配置文件中注册映射文件,如果忘记了具体操作请移步至我的上一篇博客:java后端框架——Mybatis框架搭建

        这里有一点值得我们注意的是,以往我们向通过student学生类查询major专业信息,需要在student类中重新定义专业中的属性,如:mid、mname会发生冗余。但是mybatis在封装时想到,我们只需在student类中定义一个major属性即可。将专业信息封装到学生类中,因为mid、mname本质上在major中已经定义过。这样就在学生中关联了专业。

(2)多表查询
        <association>标签

        因此多表查询,为了使major类的信息存储到student类中我们定义的major属性中去,就需要借助<resultMap>标签。整体结构如下:

//定义 resutlMap
<resultMap id="adminResultMap" type="Admin"><id column="id" property="id"/><result property="account" column="account" /><result property="password" column="password" />
</resultMap>
注: (1). resutlMap 的 id 属性是 resutlMap 的唯一标识,本例中定义为 “adminResultMap”
        (2). resutlMap 的 type 属性是映射的 POJO 类型(即该类的类型)
        (3). id 标签映射主键,result 标签映射非主键
        (4). property 设置对象属性名称,column 映射查询结果的列名称(这里因为我在IDEA中创建类的属性时名字与数据库列名保持一致故而前后相同,大家根据自己创建类的属性名而定
//使用 resultMap
<select id="findAdminInfoResultMap" resultMap="adminResultMap">SELECT id ,account,password FROM admin
</select>
注: (1). 本例的输出映射使用的是 resultMap,而非 resultType
        (2). resultMap 引用了 adminResultMap(这与上面<resultMap>中的id保持一致

        接下来我通过查询学生及其相关专业为例,演示如何映射关联数据。接口中的方法和测试程序我就不再过多赘述,参考上文即可,这里只演示映射文件内容。

    <!--对关联查询到的学生信息进行自定义映射封装--><resultMap id="studentMap" type="Student"><id column="id" property="id"></id><result column="num" property="num"></result><result column="name" property="name"></result><result column="gender" property="gender"></result>
<!--映射关联数据专业名称 先创建一个Major对象,将专业名称封装到Major对象中,再将major对象封装到Student对象中--><association property="major" javaType="Major"><result column="mname" property="name"></result></association></resultMap><select id="findStudentById" resultMap="studentMap">selects.id,s.num,s.name,s.gender,m.name mnamefrom student s inner join major m on s.majorid = m.id where s.id = #{id}</select>

注: <association>标签映射关联对象数据。该标签头中俩标签内容:

        <property>标签中是要映射关联的类的对象

        <javaType>标签放关联对象的类型

        * 如果多个查询的属性一致,只是查询结果个数不同,如去掉where条件语句,我们可以让两个select查询共同映射同一个Map,即resultMap映射地址一致。

        <connection>标签

        当我们想通过专业查询该专业有多少学生时,可以将多个学生封装到一个集合中,这时就要用到<connection>标签,将查询关联到的多条结果封装到集合中去。

    <resultMap id="majorMap" type="Major"><id column="id" property="id"></id><result column="name" property="name"></result><collection property="students" javaType="list" ofType="Student"><result column="num" property="num"></result><result column="sname" property="name"></result></collection></resultMap><select id="findMajorById" resultMap="majorMap" parameterType="int">selectm.id,m.name,s.num,s.name snamefrom major m inner join student s on s.majorid = m.id where m.id = #{id}</select>

        其中,collection 和 association 都需要配置 select 和 column 属性,两者配置方法

相同,参考上文。对应关系如下:

        测试代码 :

@Testpublic void test1(){SqlSession sqlSession = MyBatisUtil.getSqlSession();MajorDao majorDao = sqlSession.getMapper(MajorDao.class);Major major = majorDao.findMajorById(1);System.out.println(major.getName());for (Student student:major.getStudents()){System.out.println(student.getName()+":"+student.getNum());}sqlSession.close();}//Major findMajorById(int id);接口中方法

2.嵌套查询

        场景一:将原本的关联查询分成两步或多步,形成嵌套查询,这样虽然简化了sql语句,但是要进行两次或多次sql查询执行,效率劣势。

        这里同样不赘述接口方法和测试部分,若无法独立编写,请参考文章开头部分。

<!--嵌套查询,先查主表student学生表,再查关联的major专业表-->
<resultMap id="studentMap1" type="Student"><id column="id" property="id"></id><result column="num" property="num"></result><result column="name" property="name"></result><result column="gender" property="gender"></result>
<!--封装关联表数据--><association property="major" javaType="Major" select="findMajorById" column="majorid"></association></resultMap><select id="findStudentById1" resultMap="studentMap1">select*from student s where s.id = #{id}</select>
<!--嵌套查询学生关联的专业--><select id="findMajorById" resultType="Major">select name from major where id = #{majorid}</select>

<association>新属性解释:

        (1). select:指定关联查询对象的 Mapper Statement ID 为 findDeptByID(即等于子查询中的id
        (2). column="majorid":关联查询时将 majorid 列的值传入 findDeptByID,并将 findDeptByID 查询的结果映射到 Emp 的 dept 属性中(即student表的majorid通过此处传给major子表中的id,从而查出专业名称
        对应关系如下图:

        场景二:当我们通过专业表查询相关专业学生时,因为一对多关系,会导致例如:专业只有四个,但学生有五个而使查询结果个数不一致。在实际开发中,如果要对专业查询表进行分页处理,就会因此导致无法分页。

    <!--分页处理,两次查询--><resultMap id="majorMap1" type="Major"><id column="id" property="id"></id><result column="name" property="name"></result><collection property="students" javaType="list" ofType="Student" select="findStudents" column="id"></collection></resultMap><!--分两次查询,程序会先执行专业表查询,然后才会通过专业id查出学生,
这样就会固定查出四条数据的结果,分页操作会根据major表的结果执行,而不受关联表查询结果影响--><select id="findMajor1" resultMap="majorMap1">select id,name from major</select><select id="findStudents" resultType="Student">select num,name from student where majorid = #{id}</select>

        测试和接口部分代码如下: 

@Testpublic void test3(){SqlSession sqlSession = MyBatisUtil.getSqlSession();MajorDao majorDao = sqlSession.getMapper(MajorDao.class);List<Major> major = majorDao.findMajor1();sqlSession.close();}//List<Major> findMajor1();接口中方法

四、动态sql

        MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力。 如果你有使用JDBC 或其他相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么的痛苦,确保不能忘了空格或在列表的最后省略逗号。动态 SQL 可以彻底处理这种痛苦。

以教师表为例

 

1.if元素

if 标签可以对传入的条件进行判断
<select id="teachers" resultType="com.mybatispro.model.Teacher">select * from teacher<if test="num!=null">num = #{num}</if><if test="name!=null">and name = #{name}</if>
</select>

2.where元素

对于查询条件个数不确定的情况,可使用<where>元素。
<where>元素会进行判断,如果它包含的标签中有返回值的话,它就插入一个‘where’。
此外,如果标签返回的内容是以 AND 或 OR 开头,它会剔除掉 AND 或 OR。

 用法就是给上面仨<if>标签外套一个<where>标签即可

3.trim元素

where 标签其实用 trim 也可以表示。当 where 后紧随 AND 或则 OR 的 时候,就去除 AND 或者 OR。prefix:前缀,prefixOverrides:覆盖首部指定内容。
<select id="teachers" resultType="com.mybatispro.model.Teacher">select * from teacher<trim prefix="where" prefixOverrides="and|or"><if test="num!=null">num = #{num}</if><!--如果num为空,会消除name前的and保证sql语句正确--><if test="name!=null">and name = #{name}</if></trim>
</select>

4.choose元素

配合<when><otherwise>标签使用。when otherwise 相当于if else,可以没有otherwise不能没有when

    <select id="teachers" resultType="com.mybatispro.model.Teacher">select * from teacher<trim prefix="where" prefixOverrides="and|or"><choose><!--如果名字不为空,查该老师信息,否则查王老师信息--><when test="name!=null">and name = #{name}</when><otherwise>and name = '王老师'</otherwise></choose></trim></select>

5.set元素

Set 元素可以把最后一个逗号去掉,用于更改操作,保证sql语句正确性
<update id="updateTeacher" parameterType="Teacher">update teacher<set><if test="num!=null">num = #{num},</if><if test="name!=null">name = #{name},</if></set>where id = #{id}</update>

6.foreach 元素

相当于一个增强for循环。

collection 属性根据传入的参数选择list/array

item 表示集合中每一个元素进行迭代时的别名

open 表示该语句以什么开始
separator 表示在每次进行迭代之间以什么符号作为分隔符
close 表示以什么结束
@Testpublic void test3(){SqlSession sqlSession = MyBatisUtil.getSqlSession();TeacherDao teacherDao = sqlSession.getMapper(TeacherDao.class);teacherDao.deleteTeacher(new  Integer[]{1,2,3});sqlSession.commit();sqlSession.close();}//void deleteTeacher(Integer[] array);接口中方法
<delete id="deleteTeacher" ><!--删除id在(1,2,3)中的老师-->delete from teacher where id in <foreach item="id" collection="array" open="(" separator="," close=")">#{id}</foreach></delete><!--完整sql为:delete from teacher where id in(1,2,3) -->

 以上是关于mybatis的基本知识,希望能给各位带来收获!如有不正,恳请及时指出。


http://www.mrgr.cn/news/12217.html

相关文章:

  • OpenCV入门12.2:SURF与SIFT比较及SURF示例
  • 如何在没有屏幕时间密码或 Apple ID 的情况下重置 iPhone
  • 【Tomcat】Tomcat10部署war包无法启动
  • 鸿蒙(API 12 Beta3版)【使用AVScreenCapture录屏取原始码流(C/C++)】视频播放与录制
  • 手写题之链式调用
  • 全方位解析红鲸音视频会议SDK助力系统功能集成
  • 作业0827
  • 搭建ELK-Filebeat采集系统日志
  • 使用SparkGraphX进行图计算时的编码问题
  • 如何完美实现 Go 服务的平滑升级
  • 8. 为什么 Java 中 HashMap 的默认负载因子是 0.75?
  • Unity 离线文档快速访问处理文件
  • 高效能低延迟:EasyCVR平台WebRTC支持H.265在远程监控中的优势
  • Java-List分批多线程执行
  • ModBus RTU、ModBus ASCII、ModBus TCP,它们有什么区别?
  • 算法训练营|图论第二天 99.岛屿数量 100.岛屿的最大面积
  • 【北森-注册安全分析报告-无验证方式导致安全隐患】
  • 列式存储数据库(Columnar Database)
  • 趣味算法------试用 6 和 9 组成的最大数字
  • streamlit+wordcloud使用pyinstaller打包遇到的一些坑