MyBatis
- 学习MyBatis框架
1. 三层架构
-
界面层:和用户交互,调用业务逻辑层进行功能处理,显示请求的处理结果
-
业务逻辑层:接收传递的数据,完成业务逻辑;向上为界面层提供处理结果,向下问数据访问层要数据
-
数据访问层:和数据库交互,向上提供数据
不可跨层
- Spring:是整合其他框架的框架,核心是IOC(控制翻转)和AOP(面向切面编程),它由20多个模块构成(大佬)。
- SpringMVC:Spring家族的一员,专门用来优化控制器(Servlet)的,提供了极简的数据提交、数据携带、页面跳转等功能。
- MyBatis:是持久化层(就是数据访问层)的一个框架,用来进行数据库访问的优化,专注Sql语句,极简化JDBC的访问。
它是一个半成品软件,将所有的公共的、重复的功能解决掉,帮助程序快速高效的进行开发,它是可复用的,可扩展的。
4.MyBatis框架-
原是Apache的开源项目iBatis,2010迁移到Google code 改名为MyBatis,2013年迁移Git是基于Java的持久层框架。
-
主要解决的问题:
减轻JDBC的复杂性,直接使用java对象表示结果数据,让开发者更专注SQL的处理,其他工作由MyBatis完成。
-
)添加依赖
-
)添加配置文件
具体步骤:
- 新建库、表
- 新建maven项目,quickstart模板
- 修改目录,添加缺失目录和属性
- 修改pom.xml,添加Mybatis依赖、mysql依赖、添加资源文件指定
- 在idear中添加数据库的可视化
- 添加jdbc.properties数据库配置文件
- 添加SqlMapConfig.xml文件(MYbatis的核心配置文件)
- 添加完成表增删改查的功能配置文件StudentMapper.xml
- 创建测试类 测试
-
配置MyBatis核心配置文件
-
配置mapper.xml增删查改文件
select id,name,email,age from student; -
使用代码测试 完成查询所有
//使用文件流读取核心配置文件SqlMapConfig.xml InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); //创建SqlSessionFactory工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //取出SqlSession对象 SqlSession sqlSession = factory.openSession(); //完成查询 List -
切记:所有的增删改的操作后都必须手工提交事务!!sqlSession.commit();
-
Resources类
解析SqlMapConfig.xml文件,创建出相应的对象
InputStream in = Resources.getResourceAsStream(“SqlMapConfig.xml”);
-
SqlSessionFactory接口
创建SqlSessionFactory工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
-
SqlSession接口
完成sql功能的接口
- @Test //测试方法
- @Before //在Test方法执行前先执行的代码
- @After // 在Test方法执行后先执行的代码
-
单个注册
实体类别名为student -
批量注册
使用别名注册后再map中就只用写别名:
select id,name,email,age from student;
在三层架构中 业务逻辑层要通过接口访问数据访问层的功能,动态代理可以实现。
动态代理的实现规范:
- UserMapper.xml和UserMapper.java的接口必须在同一个目录下
- UserMapper.xml和UserMapper.java的文件名必须一致,后缀不管
- UserMapper.xml文件标签的id值和UserMapper.java的接口中方法的名称完全一致
- UserMapper.xml文件标签的parameterTyper属性值和UserMapper.java的接口中方法的参数类型完全一致
- UserMapper.xml文件标签的resultTyper属性值和UserMapper.java的接口中方法的返回值类型完全一致
- UserMapper.xml文件中namespace属性必须是接口的完全限定名称. com.jv.—
- 在sqlMapConfig.xml文件中注册mapper时,使用class=接口的完全限定名。
13.#{ }占位符
传参大部分使用#{ }占位符,它底层是prepareStatement对象,是安全的数据库访问防止sqsl注入。
#{ }里怎么写 要看prepareStatement参数的类型
- prepareStatement类型是简单类型(8种基本和封装+String),则#{ }里随便写
- prepareStatement类型是实体类的类型,则#{ } 里只能是类中成员变量的名称(属性名),而且区分大小写。
-
字符串拼接,一般用于模糊查询中,建议少用有sql注入风险
同样看prepareStatement参数的类型
- prepareStatement参数的类型是简单类型,则${}里随便写,但分版本,3.5.1以下的只能写value
- prepareStatement参数的类型是实体类类型,则${}里只能是类中成员变量的名称(属性名),而且区分大小写。
优化模糊查询
传统:
select id,username,birthday,sex,address from users where username like '%${name}%';用concat函数字符串拼接加#{}:
select id,username,birthday,sex,address from users where username like concat('%',#{name},'%');
2.字符串替换
使用场景:当你需要根据不同的列名来进行对应的模糊查询时,用上${}字符串替换
-
mapper接口中可用iBatis注解 @Param来标记传参,在mapper中配置sql时调用
//模糊地址和用户名查询 List
getByNameOrAddress( @Param("columnName")//模糊查询的列名 String columnName, @Param("columnValue")//模糊查询的值 String columnValue); -
mapper.xml中调用,${columnName}实现接收各种的列名 (#{}是占位符相当于 ?不可用在where后表示列名,因此要字符串替换)
select id,username,birthday,sex,address from users where ${columnName} like concat('%',#{columnValue},'%');
-
在插入语句结束后,返回自增的主键值到入参的users对象的id属性中。select last_insert_id();
select last_insert_id(); insert into users(username,birthday,sex,address) values (#{userName},#{birthday},#{sex},#{address})
标签参数:
-
keyProperty:users对象的哪个属性来接返回的主键值
-
resultType:返回的主键类型
-
order:在插入语句执行前,还是插入执行后返回的主键值
是一个全球唯一字符串,由36个字母数字中划线组成。java和mysql都提供了UUID的生成。
17.什么是动态SQL可以定义代码片段,可进行逻辑判断,可以进行循环处理(批量),是条件判断更简单。
-
:用来定义代码片段,可将所有的列名,或复杂的条件定义为代码片段供使用时调用
id,username,birthday,sex,address -
:用来引用定义的代码片段
select
from users -
:进行条件判断
-
:进行多个条件拼接,在查询、删除、更新中使用
select from users and username like concat('%',#{userName},'%') and birthday = #{birthday} and sex = #{sex} and address like concat('%',#{address},'%') -
:有选择的进行更新处理,但至少更新一列
update users where id = #{id}username = #{userName}, birthday = #{birthday}, sex = #{sex}, address = #{address}, -
:用来进行循环遍历,完成循环条件查询、批量删除、批量添加、批量更新
//循环实现 :in(2,4,6)
select from users where id in #{id} 其中参数:
- collection:指定入参的类型,List集合用list、Map集合用map、数据用array.
- item:每次循环出来的值或对象
- separator:多个值或对象或语句之间的分隔符
- open:整个循环外的前括号
- close:整个循环外的后括号
注意:多条语句一次性执行一定要开启数据库批处理(如批量更新),在properties数据库配置文件中url上添加&allowMultiQueries=true
如果入参是多个的,可以通过指定参数位置进行传参,是实体类包含不住的条件(实体类只能封装住成员变量的条件),如果某个成员变量要有区间范围类的判断,或者有两个值进行处理则实体类包不住,如:查询指定日期范围内的用户信息。
//查询指定日期范围的用户信息 ListqueryByBirthday(Date begin,Date end);
用arg0|arg1来去,默认第一个入参是0一次往后
19.入参是mapselect from users where birthday between #{arg0} and #{arg1};
如果是入参数超过一个,使用map封装查询条件,更有语义,查询条件更明确。
map.put("birBegin",sf.parse("1995-1-1"));
map.put("birEnd",sf.parse("1999-12-31"));
select
from users
where birthday between #{birBegin} and #{birEnd};
20.返回值是map
如果返回的数据实体类无法包含,可使用map返回多张表中的若干个数据,返回后这些数据之间没有任何关系就是object类型;返回的map中key就是列名或别名。
Map getReturnMap(Integer id);//接口
//测试方法中
Map returnMap = mapper.getReturnMap(15);
System.out.println(returnMap.get("username"));//username就是列名
select username,address from users where id = #{id};



