介绍
这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper
映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
初始化工程
导包
导配置
在src或resources目录下新建jdbc.properties
1 | com.mysql.jdbc.Driver = |
在src或resources目录下新建log4j.properties
1 | ### 设置### |
在src或resources目录下新建mybatis-config.xml核心配置
1 |
|
使用注解增删改查
环境准备
建库建表
1 | CREATE DATABASE `mybatis03`; |
创建Student实体类
在cn.itcast.domain包下创建Student类
1 | package cn.itcast.domain; |
创建StudentDao接口
在cn.itcast.dao包下创建StudentDao接口
1 | package cn.itcast.dao; |
配置映射关系
在mybatis-config.xml中配置映射关系,因为现在映射关系通过注解体现,所以应该扫描包含注解的接口
1 | <mappers> |
查询演示
第一步:在StudentDao接口中添加查询方法
1 | List<Student> findAll(); |
第二步:在查询方法上添加@select注解
1 | "select * from student") ( |
第三步:编写测试方法
1 |
|
形参中有多个值,在SQL中怎么获取?
1 | //@Select("select * from student where id = #{arg0} and name = #{arg1}") |
新增演示
第一步:在StudentDao接口中添加新增方法
1 | int insert(Student student); |
第二步:在新增方法上添加@Insert注解
1 | /*#{name},#{age}对应的是形参Student对象的属性的名字,表示把name,age属性的值取出来*/ |
第三步:编写测试方法,注意默认需要手动提交事务,必须手动commit
1 |
|
修改演示
第一步:在StudentDao接口中添加更新方法
1 | int update(Student student); |
第二步:在更新方法上添加@Update注解
1 | /*#{name},#{age},#{id}对应的是形参Student对象的属性的名字,表示把name,age,id属性的值取出来*/ |
第三步:编写测试方法,注意默认需要手动提交事务,必须手动commit
1 |
|
删除演示
第一步:在StudentDao接口中添加删除方法
1 | int delete(Integer id); |
第二步:在删除方法上添加@Delte注解
1 | /*#{id}对应的是形参Student对象的属性的名字,表示把id属性的值取出来*/ |
第三步:编写测试方法,注意默认需要手动提交事务,必须手动commit
1 |
|
#{}与${}的区别
以下两种写法的区别
1 | @Insert("insert into student (name,age) values('${name}',${age})") |
$底层使用Statement,最终会拼接出一个完整的SQL, insert into student (name,age) values(‘严朝阳’,12)
#底层使用PrepareStatement ,最终拼接的SQL带占位符insert into student (name,age) values(?,?)
PrepareStatement 效率高,防止SQL注入,书写更加方便。
使用注解多表查询
一对一
表关系
一对一关系中,表关系由任意一方维护,以人和身份证为例,一个人对应一个身份证,一个身份证对应一个人。本案例中由身份证表维护表关系
需求
查询所有的身份证,并且要将身份证对应的人也查询出来
实现步骤
第一步:建表
1 | DROP TABLE IF EXISTS `person`; |
第二步:创建实体类
Person 人类
1 | package cn.itcast.domain; |
Card 身份证类,因为需求是查询身份证,并且查询对应的人,所以应该是Card实体类中存放Perosn属性
1 | package cn.itcast.domain; |
第三步:创建dao接口(核心)
思考 使用2条SQL语句,查询id=1的身份证信息以及对应的人怎么查
1 | -- 第一步 查询id=1的身份证信息,找到对应的pid,值为1 |
接下来通过编写两个Dao分别完成以上两个查询语句
1.Person实体类比较简单,所以先编写PersonDao中的代码,根据id查询详细信息
1 | package cn.itcast.dao; |
2.编写CardDao
1 | package cn.itcast.dao; |
第四步:编写测试方法
1 |
|
一对多
表关系
一对多关系中,表关系由多的一方维护,以班级和学生为例,一个班级可以有多个学生,学生表应该维护表关系。
需求
查询所有班级信息,并且要将班级对应的学生信息也同时查询出来
实现步骤
第一步:建表
1 | DROP TABLE IF EXISTS `classes`; |
第二步:创建实体类
Student学生类,和上文提到的一样。有就不用创建了
1 | package cn.itcast.domain; |
Classes班级类,因为需求是查询班级,以及对应的学生,所以应该是班级类中定义List表示一堆学生
1 | package cn.itcast.domain; |
第三步:创建dao接口(核心)
思考 使用2条SQL语句,查询id=1的班级信息以及对应的学生怎么查
1 | -- 第一步 查询ID=1的班级信息 |
接下来通过编写两个Dao分别完成以上两个查询语句
1.Student实体类比较简单,所以先编写StudentDao中的代码,根据cid查询学生信息
1 | package cn.itcast.dao; |
2.编写ClassesDao
1 | package cn.itcast.dao; |
第四步:编写测试方法
1 |
|
多对多
表关系
多对多关系中表关系由中间表维护,以学生和课程为例,一个学生对应多们课程,一个课程同时对应多个学生
需求
查询所有的学生,并且要将学生对应的课程也查询出来
实现步骤
第一步: 建表
1 | DROP TABLE IF EXISTS `classes`; |
第二步:创建实体类
Course 课程类
1 | package cn.itcast.domain; |
Student 学生类,学生类之前已经定义过了,只需要添加新的course属性即可。因为需求是查询学生信息,以及对应的课程,所以应该在学生类中定义List,表示一堆课程
1 | package cn.itcast.domain; |
第三步:创建Dao接口(核心)
思考,使用2条SQL如何查询id=8的学生的信息以及对应的课程信息
1 | -- 第一步 查询id=8的学生信息 |
接下来通过编写两个Dao分别完成以上两个查询语句
1.Course实体类比较简单,所以先编写CourseDao中的代码,根据sid查询课程信息
1 | package cn.itcast.dao; |
2.编写StudentDao
1 | package cn.itcast.dao; |
第四步:编写测试类
1 |
|
注解版本的多表查询分析过程
1.需求分析,分析主要查询哪个表中的数据,顺便要查询出的表的名字
2.编写实体类,通过需求分析,可以确定实体类和实体类之间的关系,是谁包含谁
3.编写dao,先编写SQL语句,第一条SQL 肯定是 select * from 表 , 第二条 select * from 表 where x= 主表中查询出的某个数据
4.分别编写两个Dao,先编写第二个SQL对应的DAO,然后再编写第一个SQL对应的DAO
SQL功能类
介绍
我们在使用注解开发的时候有一些不足
- sql语句中的关键字可能不小心写错。
- 不方便执行动态SQL语句。
那么SQL功能类是个不错的选择。
使用方式分为2步
- 第一步:使用SQL对象生成要执行的sql语句
- 第二步:使用@SelectProvider替换之前的@Select,使用@InsertProvider替换之前的@Insert….
环境搭建
创建表
1 | CREATE TABLE `user`( |
创建实体类
1 | package cn.itcast.domain; |
定义UserSQL功能类
在cn.itcast.sql 包下新建UserSQL功能类
1 | package cn.itcast.sql; |
定义UserDao接口
在cn.itcast.dao包下新建UserDao接口
1 | package cn.itcast.dao; |
查询@SelectProvider
普通查询
1.在UserSQL功能类中添加生成SQL语句的方法
1 | /**功能:生成查询全部的SQL*/ |
2.在UserDao接口中添加findAll方法
1 | .class, method = "findAll") (type = UserSQL |
3.测试方法
1 |
|
动态SQL查询
1.在UserSQL功能类中添加生成SQL语句的方法
1 | /**功能:根据传入的条件动态拼接查询SQL*/ |
2.在UserDao接口中添加findAll方法
1 | .class,method = "findByCondition") (type = UserSQL |
3.测试方法
1 |
|
新增@InsertProvider
1.在UserSQL功能类中添加生成SQL语句的方法
1 | /**功能:插入*/ |
2.在UserDao接口中添加insert方法
1 | .class,method = "insert") (type = UserSQL |
3.测试方法
1 |
|
更新@UpdateProvider
1.在UserSQL功能类中添加生成SQL语句的方法
1 | /**生成根据ID更新的SQL*/ |
2.在UserDao接口中添加update方法
1 | .class,method = "update") (type = UserSQL |
3.测试方法
1 |
|
删除@DeleteProvider
1.在UserSQL功能类中添加生成SQL语句的方法
1 | /**生成根据uid删除的SQL语句*/ |
2.在UserDao接口中添加deleteByUid方法
1 | .class, method = "deleteByUid") (type = UserSQL |
3.测试方法
1 |
|