之前介绍了一些比较适用的框架,今天来介绍一个持久层框架——MyBatis。
Mybatis 介绍:
框架的作用:
Mybatis是一个数据持久层框架(dao层),数据持久化,将数据从内存中存储到硬盘中
框架的特点:
Jdbc的缺点:
- 代码重复性高,反复的建立连接
- Sql语句,采用硬编码,sql语句写在java代码中
- 参数的植入,它跟java的耦合性高
- 结果集的处理非常的麻烦
Mybatis优点:
- 让程序员只关注,sql语句不需要去关注对应的代码
- 帮助我们处理结果集
Mybatis的原名 ibatis
简单,很灵活,属于半orm框架,而Hibernate属于orm框架
Mybatis 快速搭建
- 准备数据库,在准备实体类
- 配置文件
- 书写配置文件 SqlMapconfig.xml
- 书写映射文件 UserMapper.xml
-
-
"test"> -
-
SELECT * FROM t_user WHERE id = #{id}
-
-
- 书写测试代码MybatisDemo
-
public void fun() throws IOException {
-
InputStream in = Resources.getResourceAsStream(
"sqlMapConfig.xml");
-
-
SqlSessionFactory build =
new SqlSessionFactoryBuilder().build(in);
-
SqlSession sqlSession = build.openSession();
-
Object user = sqlSession.selectOne(
"test.selectUserById",
1);
-
System.out.println(user);
-
}
Mybatis环境解释:
1. 核心配置文件
命名:命名没有默认,一般叫做sqlMapConfig
路径:maven放在resource中
内容:环境:
事务管理器
连接池
(获得和数据库的连接)
读取映射文件:
2. 映射文件
名字 位置,没有要求 名字:实体类+Mapper.xml(mybatis) 实体类+ .xml(ibatis 命名规范)
Namespace 命名空间, 作用用来区分方法名
两张表 都有一个查询的方法, 名字一致 selectById, 没办法区分到底哪个表的操作,namespace这个时候起作用
Sql语句:
-
-
SELECT * FROM t_user WHERE id = #{id}
-
id是java代码中定位到这个语句 parmeterType 参数类型 ResultType返回值类型
#{id}占位符 id名字可以随意,但是一般和字段名保持一致
Mybatis结合log4j
1. 导包
Log4j的作用:在控制台上显示日志
-
-
-
log4j
-
log4j
-
1.2.17
-
2. 导入一个文件
简单使用mybatis的增删改查:
- 通过id查找用户
- 通过名字模糊查询
Mybatis设置参数的方式:
PreparedStatement Statement
Sql注入:
通过客户端传入参数的方式,将sql语句注入程序中,这样的情况就叫sql注入
$ 先把传过来的参数与SQL语句进行拼接, 形成新的sql语句直接执行整个sql语句, 存在sql注入风险
# 占位符 先把写好的sql语句进行预编译,再将参数设置进来。自动检查参数中是否包含sql语句,如果包含就执行失败, 避免了sql语句注入
建议全部使用#{}占位符的方式.
配置映射文件:
-
-
SELECT * FROM t_user WHERE name LIKE
"%"#{name}
"%"
-
测试代码:
-
public void fun1(){
-
String name =
"张";
-
List
-
System.out.println(users);
-
}
- 增加用户
如果是增删改操作,必须是提交事务,最终才会对数据库进行修改。
1. 修改用户
Update
2. 删除用户
Delete
在插入一条数据之后,马上要根据这条数据向另外一张表中插入数据
主键生成策略:
代理主键:
自动递增:
在数据库中的机制:再生成新的数据之前,先生成记录再出插入主键
KeyProperty 代表的是对象的属性名
resultType 查出来主键的类型
order 排序如果是自动递增就用after 如果是uuid 就用before
-
"id" resultType=
"int" order=
"AFTER">
-
SELECT LAST_INSERT_ID()
-
-
Uuid:
机制:在生成主键,再去生成记录,如果采用uuid机制,在设计数据库的时候长度必须大于等于36
-
"id" resultType=
"int" order=
"BEFORE">
-
Select uuid()
-
自然主键
原始dao层开发
SqlSessionFactoryBuilder 读取配置文件,调用他的build
SqlSessionFactory 创建SqlSession
SqlSession 封装了方法(在每个方法中都重新创建,建议使用局部变量)
Dao依赖于SqlSessionFactory
-
public
class UserDaoImpl implements UserDao {
-
-
private SqlSessionFactory sqlSessionFactory;
-
-
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
-
this.sqlSessionFactory = sqlSessionFactory;
-
}
-
public User selectUserById(Integer id) {
-
SqlSession sqlSession = sqlSessionFactory.openSession();
-
User user = sqlSession.selectOne(
"test.selectUserById",id);
-
return user;
-
}
-
}
代理dao(Mapper接口)开发
前提条件
1.接口的名字建议和映射文件的名字保持一致
Namespace 必须和接口的相对路径名保持一致
2. 在配置文件中的resultType必须和接口中的方法名的返回值类型保持一致
3,.配置文件中的参数类型,必须和接口中的参数的类型保持一致
4.配置文件中的id必须和接口中的方法名保持一致
注意:方法中的参数只能有一个
selectOne selectList是根据mapper中的方法返回值的类型决定的
sqlMapconfig文件详解
配置文件中的属性顺序不能更改必须按照上面的顺序
typteAliases 别名
-
-
-
<
package name=
"com.hd.pojo">
package>
-
package 自动为实体类起两个别名 一个是类名
一个是类名首字母小写
比如 com.hd.pojo.User User/user
typeHandlers类型转换器
实现jdbc(数据库中的类型) 和 java的类型的转换,一般情况下不需要自己去改,有一些特殊情况,需要手动映射
输入类型和输出类型
输入类型
普通类型:
还能使用pojo类型
Pojo的封装类:
既包含普通类型也包含其他的类型,在mapper中所有的方法的参数都不需要去考虑,把真正的参数放到封装类中,并添加get/set方法,配置文件要采用ognl表达式的方式去取值
Map
输出类型:
ResultType
自动转换,名字保持一致才会自动转换
ResultMap:
手动转换,如果名字不一致不会转换,需要手动转换
-
"com.hd.resultMap.UserMapper">
-
"selectUser" type=
"com.hd.pojo.User">
-
"password" column=
"psd">
-
-
-
-
parameterType=
"com.hd.queryVo.QueryVo"
-
resultType=
"selectUser">
-
SELECT * FROM t_user WHERE id = #{id}
-
ResultMap 不能用resultType
里面的值是其他地方定义的resultMap中的id值
ResultMap :type 将转化的类型
Id: 主键 property(类中的属性名) column(数据库字段名) JavaType jdbcType TypeHandler
Result 普通属性
动态SQL
if标签
-
<
if test=
"id != '' and id != null">
-
and id = #{id}
-
if>
Test 使用ognl表达式的发方法取值 可以if条件
并且 and
或者 or
如果有多个条件,不知道是第一个成立and的位置不好放,就在任何一个位置都可能会出异常,使用where标签解决
Where标签
能够自动去除 前and
如果所有的条件都不成立,那么where关键字自动去除
Foreach 标签
-
"array" open=
"(" close=
")" separator=
"," item=
"id">
-
#{id}
-
Collection 用来识别是什么数据类型
数组: array
List集合: list
Set集合: set
封装类: 必须是封装类中的属性名
Open 在遍历数组前的sql语句
Close 遍历之后再加上一段sql语句
Separator 遍历数组,每个元素之间的分隔符
Item 遍历时给当前元素起的名字,必须和占位符中的名字保持一致
Index 下标
Sql 片段
-
select
">
-
SELECT sex,address,name
-
-
"select">
Include refid 属性对应就是sql片段中的id 名
多表查询
1对1查询
实现1对1查询的结果集的封装
两种方法:
新建一个实体类,实体类中包含所有想要转化的列名
可以建一个类,让这个类去继承一个类
ResultMap
在原来的实体类中增加一个另外一个实体类类型的属性,并添加get set方法,在结果集处理的时候采用ResultMap
ResultMap中
注意:如果字段名和属性不写转化,就不会转化,想要将查询到的结果全部封装到实体类中就必须全部都写
1对多查询
resultType
新建一个实体类,实体类中包含所有想要转化的列名
可以建一个类 让这个类去继承一个类
ResultMap
添加属性 集合 并且添加get/set方法
-
"companyView" type=
"Company">
-
"id" column=
"companyId">
-
"name" column=
"companyName">
-
"users" javaType=
"list" ofType=
"User">
-
"id" column=
"id">
-
"name" column=
"name">
-
"sex" column=
"sex">
-
"password" column=
"password">
-
"address" column=
"address">
-
-
Collection property 是实体类的属性名,javaType(集合 list set)
ofType 封装集合中每个元素的类型
缓存(Redis Memache)
延迟加载
逆向工程
逆向工程:通过一方生成另一方
hibernate auto属性 update 自动根据你的配置文件生成表
mybatis
根据表自动创建 实体类 接口类 映射文件
使用maven实现逆向工程
1 mysql驱动, 配置文件中将你本地的mysql数据库驱动的绝对路径改掉
2 数据库名 用户名 密码
3 改变生成 实体类 映射文件 mapper 的生成路径(可选)
4 改数据库表名 实体类名 注意实体类名千万不能重复
注意点击插件运行的时候:点一次
Spring 整合 mybatis
spring 管理对象
SqlSessionFactory
sqlSession
- 导包
spring 所有包
-
-
-
org.springframework
-
spring-context
-
5.0.2.RELEASE
-
-
-
-
-
org.springframework
-
spring-core
-
5.0.2.RELEASE
-
-
-
-
-
org.springframework
-
spring-beans
-
5.0.2.RELEASE
-
-
-
-
-
org.springframework
-
spring-test
-
5.0.2.RELEASE
-
test
-
-
-
-
org.springframework
-
spring-jdbc
-
5.0.2.RELEASE
-
-
-
-
org.springframework
-
spring-tx
-
5.0.2.RELEASE
-
mybatis 所有包
-
-
-
org.mybatis
-
mybatis
-
3.4.5
-
整合包
-
-
-
org.mybatis
-
mybatis-spring
-
1.3.0
-
数据库驱动包
-
-
mysql
-
mysql-connector-java
-
5.1.37
-
日志包
-
-
-
log4j
-
log4j
-
1.2.17
-
另外安利一个学习教程:1.IT段子手详解MyBatis遇到Spring 秒学Java SSM开发大众点评 难度中级(视频+源码)