# 简单查询
驼峰命名配置:
一般数据库的字段名都是下划线分隔,但是 Java 里面是驼峰命名,就会导致查询时数据库的字段映射不到 Java 类里面,所以需要开启转换
<settings> | |
<setting name="mapUnderscoreToCamelCase" value="true"/> | |
</settings> |
对于查询结果,我们可以做如下更改:
- 查询结果映射为实体类
<select id="studentList" resultType="Student"> | |
select * from student | |
</select> |
- 查询结果映射为 Map
<select id="selectStudent" resultType="Map"> | |
select * from student | |
</select> |
其中一个 Map
就是一行查询结果,当然,对应的 mapper 接口方法就需要换成:
public interface TestMapper { | |
List<Map> selectStudent(); | |
} |
- 指定映射规则
<resultMap id="Map" type="Student"> | |
<result column="sid" property="sid"/> | |
<result column="name" property="name"/> | |
</resultMap> | |
<select id="selectStudent" resultType="Map"> | |
select * from student | |
</select> |
- 指定构造器
<resultMap id="Map" type="Student"> | |
<constructor> | |
<arg column="sid" javaType="Integer"/> | |
<arg column="name" javaType="String"/> | |
</constructor> | |
</resultMap> | |
<select id="selectStudent" resultType="Map"> | |
select * from student | |
</select> |
但是查询一般会附带条件,所以 select
标签除了 resultType
之外,还需要 parameterType
标签:
<select id="getStudentBySid" parameterType="int" resultType="Student"> | |
select * from student where sid = #{sid} | |
</select> |
通过使用 #{xxx}
或是 ${xxx}
来填入我们给定的属性,实际上 Mybatis 本质也是通过 PreparedStatement
首先进行一次预编译,有效地防止 SQL 注入问题,但是如果使用 ${xxx}
就不再是通过预编译,而是直接传值,因此我们一般都使用 #{xxx}
来进行操作。
其实插入,删除这些需要传递参数的语句都会用到
#{}
。
# 复杂查询
# 一对多
一个老师可以教授多个学生,需要一次性将 A 老师的学生全部映射给 A 老师的对象:
@Data | |
public class Teacher { | |
int tid; | |
String name; | |
List<Student> studentList; | |
} |
之前编写的都是非常简单的映射,此时需要使用 resultMap
来自定义映射规则。
<select id="getTeacherByTid" resultMap="asTeacher"> | |
select *, teacher.name as tname from student | |
inner join teach on student.sid = teach.sid | |
inner join teacher on teach.tid = teacher.tid where teach.tid = #{tid} | |
</select> | |
<!--teach 是中间表,连接学生和老师两张表 --> | |
<resultMap id="asTeacher" type="Teacher"> | |
<id column="tid" property="tid"/> | |
<result column="tname" property="name"/> | |
<collection property="studentList" ofType="Student"> | |
<id property="sid" column="sid"/> | |
<result column="name" property="name"/> | |
<result column="sex" property="sex"/> | |
</collection> | |
</resultMap> |
<resultMap>
的 id
要与 <select>
标签相关联。
之前说过,实际项目中联表查询有时会非常复杂,所以有时会直接选择手写 sql 语句使用
jdbc
而不是使用 Mybatis。
# 多对一
现在修改一下 Student
和 Teacher
两个类:
@Data | |
@Accessors(chain = true) | |
public class Student { | |
private int sid; | |
private String name; | |
private String sex; | |
private Teacher teacher; | |
} | |
@Data | |
public class Teacher { | |
int tid; | |
String name; | |
} |
我们想要通过某个条件查询学生数据,每一行学生都要顺带查询老师的信息,导致出现多对一查询:
<select id = "test" resultMap = "sTot"> | |
select * , teacher.name as tname from Student | |
left join teach on teach.sid = student.sid | |
left join teacher on teach.tid = teacher.tid | |
</select> | |
<!-- 查询结果里面不需要写 teacher.tid,因为学生表中有 --> | |
<resultMap id = "sTot" type="Student"> | |
<id column="sid" property="sid"/> | |
<result column="name" property="name"/> | |
<result column="sex" property="sex"/> | |
<association property="teacher" javaType="Teacher"> | |
<id column="tid" property="tid"/> | |
<result column="tname" property="name"/> | |
</association> | |
</resultMap> |
其实不论是用 <collection>
还是 <association>
,都是对查询结果的一种处理方式罢了。
# 事务
因为内容比较少,就放到复杂查询里面一起讲解。
我们使用 Mybatis,在 Java 代码层面是使用 SqlSession
,其实打开一个 SqlSession
,相当于打开了一个事务,如果关闭了自动提交,在调用了修改数据库的语句,就需要 commit
。
try (SqlSession sqlSession = MybatisUtil.getSession(false)){ | |
TestMapper testMapper = sqlSession.getMapper(TestMapper.class); | |
testMapper.addStudent(new Student().setSex("男").setName("小王")); | |
testMapper.selectStudent().forEach(System.out::println); | |
// 回滚 | |
sqlSession.rollback(); | |
// 提交 | |
sqlSession.commit(); | |
} |
# 参考
https://www.yuque.com/qingkongxiaguang/javaweb/gn0syt#3203fe15