mysql
mysql-connector-java
5.1.6
org.mybatis
mybatis
3.5.2
log4j
log4j
1.2.12
1.2、创建Mybatis全局配置文件
- 全局配置文件位置
- 全局配置文件
- 其它相关配置标签
1.3、创建接口(interface)@Alias("emp") //别名注释,写在类上给类起别名
public interface UserDao{
public User queryById(int u_id);
public int addUser(int u_id,String u_username,String u_sex);
public int delUser(int u_id);
public int updateUser(int u_id,String u_sex,String u_username);
}
1.4、映射文件—实现:增删改查
- 必须有对应的接口的文件,映射文件用于实现接口并完成关系映射
1.5、运行程序,操作数据库 1.5.1、步骤:
-
使用全局配置文件得到SqlSessionFactory
-
使用SqlSessionFactory,获取SqlSession来进行增删改查,一个SqlSession代表与数据库的一次会话,用完需要关闭。
-
根据此方法自动为接口创建一个代理对象,去实现增删改查功能:
- UserDao userdao = session.getMapper(UserDao.class);
-
SqlSession和connection都是非线程安全,因此每次都要创建新的对象
public class MybatisQueryTest {
public static void main(String[] args) throws IOException {
//1-加载配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//2-获取工厂
SqlSessionFactory factory = new
SqlSessionFactoryBuilder().build(inputStream);
//3-从工厂拿取session
SqlSession session = factory.openSession();
//4-从session里面拿取mapper
UserDao userdao = session.getMapper(UserDao.class);
//5-业务处理
User user = userdao.queryById(1001);
System.out.println(user);
//6、关闭资源
session.close();
}
}
1.5.2、事务提交—增删改
- SqlSession session = factory.openSession();默认为手动提交,
- 必须添加 session.commit(); 否则会回滚
- 可以设置为自动提交:factory.openSession(true);
public class MybatisDelTest {
public static void main(String[] args) throws IOException {
//1-加载配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//2-获取工厂
SqlSessionFactory factory = new
SqlSessionFactoryBuilder().build(inputStream);
//3-从工厂拿取session
SqlSession session = factory.openSession();
//4-从session里面拿取mapper
UserDao userdao = session.getMapper(UserDao.class);
//5-业务处理
int num = userdao.delUser(1015);
System.out.println(num);
//7-提交事务,否则回滚
session.commit();
//6、关闭资源
session.close();
}
}
二、ORM对象关系映射
定义: Object-Relational Mapping,它的作用是在关系型数据库和对象之间作一个映射,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。
2.1、传入参数 2.1.1、传入多个参数1)默认名称
接口信息:
public User query(String name,String sex); //接口方法
映射文件:
2)自定义名称
接口信息:
//若是形参多,不易辨认,可以通过@Param("name")来映射,这样封装map时的key可以自己设定
public User query(@Param("name") String name,@Param("sex") String sex); //接口方法
映射文件:
2.1.2、传入pojo对象
若多个形参均为数据模型pojo的属性,直接传入pojo
传入数据类型设置:parameterType=“pojo全类名或者别名”,也可以不写,直接使用#{属性}调用属性值
接口信息:
//如果多个参数正好是数据模型pojo,我们可以设置模型参数,直接传入pojo public boolean addUser(User user); //接口方法
映射文件:
方法调用:
//创建user
User user = new User();
user.setSex("男");
//业务处理
List list = userdao.queryMan(user);
2.1.3、传入Map(万能)
如果多个参数正好是数据模型pojo,我们可以设置模型参数,直接传入pojo
传入数据类型设置:parameterType=“map”,也可以不写,直接使用#{key}调用value
接口信息:
public User querytree(Mapmap); //接口方法
映射文件:
方法调用:
//业务处理 Map2.1.4、传入TO(Transfer Object)数据传输对象map = new HashMap(); map.put("name", "自来也"); map.put("sex", "男"); User user = userdao.querytree(map); System.out.println(user);
Page{
int index;
int size;
}
2.1.5、注意事项
- 形参若传入对象,对象的属性在映射文件中也能使用
#{Object.属性}来获取
- **Collection(List、set)以及数组也会封装进map,List和数组还能通过索引调用 **
#{List[0]} //数组或者list均可如此
-
#{ }和${ }之间的区别
-
#{ }:以预编译的形式,将参数设置到sql语句中,起PreperStatement的功效,可以防止sql注入。本质就是jdbc里面的?,一个占位符。
-
${ }:是一个直接映射过来的数据,JDBC很多地方不支持占位符,一般只是参数使用占位符?,因此需要拼接语句的地方,必须使用它。但是存在注入风险
-
#{ }有更丰富的用法:
规定参数的一些规则:
javaType、jdbcType、mode(存储过程)…
oracle不能识别null类型 需要指定类型 #{email,jdbcType=NULL} 默认jdbcType=OTHER
-
接口信息:
//接口设置返回数据为List<> public ListqueryMan(String sex);
映射文件:
2.2.2、返回一个Map
优势:查询多字段,返回一个Map,并且可以指定某属性作为key
接口信息:
//指定某字段作为key
@MapKey("u_id")
public Map queryWoman(String sex);
映射文件:
3、添加返回数据映射
三、关联查询 3.1、关联查询添加返回数据类型
public class CourseInfo {
private Integer id;
private String date;
//Course的引用数据类型
private Course course;
//Staff的引用数据类型
private Staff teacher;
}
public class Course {
private Integer coId;
private String coName;
private String coType;
private Integer coMaxstu;
private String coPrice;
private String coOncetime;
private String coImage;
private String coDescribe;
private String coBeizhu;
private Integer coFlag;
}
public class Staff {
private Integer staffId;
private String staffName;
private String staffGender;
private String staffTel;
private String staffJob;
private String staffPower;
private String stadium;
private String isLogin;
private String staffState;
}
3.1.1、直接映射
3.1.2、< association >标签映射
3.1.3、< collection >关联查询集合封装
3.1.4、关联查询
3.2、分步查询
如何分步:
- 对象的封装分为多步,首先查询封装非引用数据类型
- 再进行通过已查询数据,获取引用数据类型的相关数据
3.3、延迟查询
定义:在上述引用对象被使用时才会被查询。
实现方式:
- 使用了分步查询
- 对默认配置进行两个修改
在全局文件中进行设置
完成这两个配置后,我们的分步查询就变为延迟查询。分步查询只做第一步,后续查询步骤被使用时才会进行
四、动态sql作用:处理复杂查询逻辑时,需要动态生成sql语句,这一步可以在java后台自己进行拼接。而Mybatis已经提供了完整的SQL语句拼接功能。
ps:下面所有的实现方法,传入的形参均为pojo;一般传入的是pojo或者map,可以使用属性名和key来获取属性值和value
4.1、< if >标签< if >标签,判断为真,将查询语句拼入
4.2、< where >标签select * from user where type='团课' and id=#{id} and username=#{username}
**作用:< if >标签的最常用应用场景为条件查询,而最开头为where,后面是and,拼接相对不容易。< where >会自行判断,并删除第一个 and 或者 or **
- 解决方式一
select * from user where 1=1 and id=#{id} and username=#{username}
- 解决方式二
4.3、< trim >标签select * from user and id=#{id} or username=#{username}
作用:用于解决拼接整体后的前后缀问题:
< trim >的四个属性:
- prefix:给拼接后的字符串加一个前缀
- prefixOverrides:给拼接后的字符串去掉一个前缀
- suffix:给拼接后的字符串添加一个后缀
- suffixOverrides:给拼接后的字符串去掉一个后缀
条件查询的解决方案三:
4.4、< choose >分支语句标签id=#{id} and username=#{username} and
作用:前端页面是一个输入框,输入框可以输入姓名、ID、或者其它信息,输入一条信息,但是存在多种可能,这时候的处理就需要分支语句
和< if >的区别:< choose >只能选择其中一条路走,< if >会都进行判断
4.5、< set >标签where course.co_id=#{course} where staff.staff_id=#{teacher} where 1=1
作用:修改属性时,去除后面的逗号。这里可以使用< trim >,或者直接用 mybatis-plus 更方便
4.6、< foreach >标签update user where username=#{u_username}; u_id=#{u_id}, u_sex=#{u_sex},
作用:遍历传入的集合
- collection:指定要遍历的集合
- item:将当前遍历出的元素赋值给指定变量,用#{变量名}能取出变量值即当前遍历值
- separator:每个元素直接的分隔符
- open:遍历后的结果拼接一个开头字符
- close:遍历后的结果拼接一个结尾字符
- index:索引
- 遍历list的时候,index是索引,item是当前值
- 遍历map的时候,index是key,这里引用key时必须使用${},因此这里不是占位符,item是map的值
4.6.1、mysql环境下的 foreach 批量插入
应用场景:< foreach >标签也能用于数据批量插入
4.6.2、oracle环境下的 foreach 批量插入五、注解开发 5.1、增删改查注解
1)注解
- @Insert: 实现新增
- @Delete:实现删除
- @Update:实现更新
- @Select:实现查询
2)格式与用法
- 注解写在要实现的方法上
- @Select(“写入查询语句”)
@Select("select * from course where co_id=#{id}")
public Course queryByCourseId(Integer id);
5.2、结果集映射注解
5.2.1、基本数据类型
1)注解
- @Results:表示结果集注解;id 表示映射集别名;value = { 映射集 }
- @Result:表示属性映射;id 表示这是主键序号;column 表示字段名,property 表示属性名
2)实例
@Select("select * from arrange_course where arrange_course.ti_id IS NOT NULL AND arrange_course.DATE IS NOT NULL")
@Results(id="courseInfo",value={
@Result(id = true,column = "arrange_id",property = "id"),
@Result(column = "co_id",property = "courseId"),
@Result(column = "staff_id",property = "teacherId")
})
public List getAllTuankeCourseInfo();
5.2.2、引用数据类型
使用注解必须使用分步查询,使用其它方法的查询结果赋值
1)注解
-
@one:表示查询的结果为单个对象
- one:为Result的属性,用于给引用数据类型赋值,接收单个对象
- column:此时的column表示传入的参数
-
@Many:表示查询的结果为多个对象,是ArrayList 集合
- many:为Result的属性,用于给引用数据类型赋值,接收多个对象
- column:此时的column表示传入的参数
2)使用
@Select("select * from arrange_course where arrange_course.ti_id IS NOT NULL AND arrange_course.DATE IS NOT NULL")
@Results(id="courseInfo",value={
@Result(id = true,column = "arrange_id",property = "id"),
@Result(column = "co_id",property = "courseId"),
@Result(column = "staff_id",property = "teacherId"),
@Result(property = "teacher",column = "staff_id",one=@One(select = "mapper.CourseInfoMapper.queryByStaffId")),
@Result(property = "course",many=@Many(select = "mapper.CourseInfoMapper.queryAllCourse"))
})
public List getAllTuankeCourseInfo();
@Select("select * from staff where staff_id=#{id}")
public Staff queryByStaffId(Integer id);
3)@ResultMap:结果集映射可以被其它方法使用
@Select("......")
//使用注解和@Results的id
@ResultMap("courseInfo")
public List conditionQuerySijiaoCourseInfo(Map map);
5.2.3、延迟查询
在最后加 :fetchType = FetchType.LAZY
@Result(property="teacher",column="staff_id",one=@One(select = "CourseInfoMapper.queryByStaffId"),fetchType = FetchType.LAZY)5.3、动态sql注解 5.3.1、动态SQL的纯注解方式
- 在查询语句外加{ }
- 前后加< script >< /script >
- 其它部分可以完全按照xml格式进行书写
@Select({""
})
@ResultMap("courseInfo")
public List conditionQueryTuankeCourseInfo(Map map);
5.3.2、使用java生成查询语句
@SelectProvider 可以调用 java生成的SQL语句,常用属性为:
- type:表示返回的数据类型
- method :表示调用的方法
使用实例
@SelectProvider(type = SubjectSqlProvider.class, method = "getSubjectTestProvider")
public Course getCourseById(@Param("id") int id);
public String selectUserById(Map para){
return new SQL(){{
SELECT("*");
FROM("t_course");
WHERe("id="+para.get("id"));
}}.toString();
}



