1. MyBatis
MyBatis 是基于 JAVA 的持久层框架,它内部封装了 JDBC
通过 xml 或者 注解 方式使将要的执行各种 statement 配置起来 , 并通过 java对象和statement中SQL的动态参数进行映射生成最终执行的SQL语句
执行完SQL语句 并将结果映射为java对象返回 使用ORM 思想解决问题
2. ORM
Object Relational Mapping 对象关系映射 持久化数据和实体对象的映射模式
3. 使用
导入 mybatis.jar 和mysql.jar
在src下创建映射配置文件 名字无所谓
- ```xml <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN” “http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
在src下创建核心配置文件
-
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 默认配置-->
<environments default="ie">
<!-- 配置名-->
<environment id="ie">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!-- 驱动-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mysql"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 映射类-->
<mappers>
<!-- 映射类名称-->
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
加核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
获取sqlsession 工厂对象
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
执行映射配置文件的sql语句
List<Object> objects = sqlSession.selectList("StudentMapper.any");
释放资源
sqlSession.close();
is.close();
4. Resources 加载资源工具类
- Resources.getResourceAsStream(String fileName) 通过类加载器返回指定资源的字节输入流 与获取类加载 加载指定资源字节输入流一样
5. SqlSessionFactoryBuilder 工厂对象功能类
- new SqlSessionFactoryBuilder().build(is); 通过指定资源字节输入流获取SqlSessionFactory工厂对象
6. SqlSessionFactory 对象
- openSession() 获取sqlsession 构建者对象 并开启手动提交事务
- openSession(boolean auotoCommit) 获取sqlsession 构建者对象 true为自动提交事务
7. SqlSession
构建者对象接口 用于执行 SQL 管理事务 接口代理
- selectList(String Statement , object parameter) 执行查询语句 并返回list集合
- selectList(String Statement , object parameter) 执行查询语句 返回一个结果对象
- inser(String Statement , object parameter) 执行新增语句,返回影响行数
- update(String Statement , object parameter) 执行修改语句,返回影响行数
- delete(String Statement , object parameter) 执行删除语句,返回影响行数
- commit() 提交事务
- rollback() 回滚事务
- getMapper(Class
<T>
cls) 获取指定接口的代理实现类对象 - close() 释放资源
8. 映射配置文件
mapper 核心根标签
- namespace属性 名称空间
select 查询标签
- id属性 唯一标识
- resultType属性 指定结果映射对象类型 类路径 增删改可以不指定类因为返回的是一个影响行数
- parameterType属性 指定参数映射对象类型 指定执行时传递的parameter类型
- SQL语句获取参数 #{属性名}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="StudentMapper">
<select id="any" resultType="com.xxx..xx" parameterType="java.lang.long">
select * from mysql where id = #{id}
</select>
<insert id="insert" parameterType="笔记.jdbc.src.Student">
insert into studen value (#{id},#{name},#{age})
-- 从Student 中传递 id name age属性
</insert>
</mapper>
9. 核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration根标签-->
<configuration>
<!-- environments配置数据库环境 default属性指定使用哪一个-->
<environments default="ie">
<!-- environment配置数据库环境 id属性唯一标识-->
<environment id="ie">
<!-- transactionManager事务管理 type属性 采用jdbc默认的事务管理-->
<transactionManager type="JDBC"></transactionManager>
<!-- dataSource数据源信息 type属性 连接池 -->
<dataSource type="POOLED">
<!-- property连接数据库的配置信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mysql"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- mappers引入映射配置文件-->
<mappers>
<!-- mapper 引入指定的映射配置 resource属性 指定映射配置文件的名名称-->
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
10. 数据库连接配置引入
<properties>
引入数据库连接配置文件标签- resource属性 数据库连接配置文件路径
获取连接参数
- ${键名}
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mysql
username=root
password=123456
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration根标签-->
<configuration>
<!-- environments配置数据库环境 default属性指定使用哪一个-->
<properties resource="笔记/mybatis/src/config.properties">
<environments default="ie">
<!-- environment配置数据库环境 id属性唯一标识-->
<environment id="ie">
<!-- transactionManager事务管理 type属性 采用jdbc默认的事务管理-->
<transactionManager type="JDBC"></transactionManager>
<!-- dataSource数据源信息 type属性 连接池 -->
<dataSource type="POOLED">
<!-- property连接数据库的配置信息-->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!-- mappers引入映射配置文件-->
<mappers>
<!-- mapper 引入指定的映射配置 resource属性 指定映射配置文件的名名称-->
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
11. 起别名
在映射配置中 我们resultType属性需要提供 类的全路径 可以在核心配置文件中起别名来简写
<typeAliaser>
为全类名起别名的父标签<typeAlias>
为全类名起步名的子标签属性:
- type 指定全类名
- alias 指定别名
<package>
为指定包下所有类起别的子标签 别名就是类名
<typeAliases>
<typeAlias type="笔记.jdbc.src.Student" alias="student"></typeAlias>
</typeAliases>
12. LOG4J
在核心配置文件添加
<settings>
<setting name="logImpl" value="log4j"/>
</settings>
并配置好log4j.properties 配置
13. 分层思想
控制层(controller) ====> 业务层(service) ====> 持久层(dao)
持久层 对接数据库
业务层 处理业务逻辑 此处只是暂时直接调用dao层的方法
控制层 使用 test类
14. 接口代理
通过接口代理 我们只需要写dao层的接口 由MyBatis 框架根据接口的定义来创建接口的动态代理对象
- 映射配置文件中的名称空间必须与dao层接口的全类名相同
- 映射配置文件中的增删改查的id属性必须和dao层接口的方法名相同
- 映射配置文件中的增删改查标签的parameterType属性必须和dao层接口方法的参数相同
- 映射配置文件中的增删改查标签的resultType属性必须和dao层接口的返回值相同
getMapper(Class<T>
cls) 获取指定接口的代理实现类对象
mybatisdemo01 mapper = sqlSession.getMapper(mybatisdemo01.class);
14.1. 源码分析
通过getMapper()方法 获取到 org.apache.ibatis.binding.MapperProxy 代理对象 底层使用 JDK 的动态代理技术 帮我们实现代理实现类对象
执行方法时调用了 mapperMethod.execute()方法 通过switch语句 判断操作类型是增删改查操作
通过SqlSession 方法来执行
15. 动态SQL
可以根据SQL语句动态根据条件查询
<where>
条件标签 如果有动态条件 则使用该标签替代where关键字<if>
条件判断标签 test属性 条件控制 如果成立则拼接SQL语句
<select id="dongtaisql" resultType="studen">
select * from stden
<where>
<if test="id != null">
id = #{id}
</if>
<if test="age != null">
and age = #{age}
</if>
</where>
</select>
<foreach>
循环遍历标签 适用于多个参数或者的关系- collection属性 参数容器类型(list集合 array数组)
- open属性 开始的sql语句
- close属性 结束的sql语句
- item属性 参数变量名
- separator属性 分隔符
<!-- select * forme studen id in(1,2,3)-->
<select id="selectbyids" resultType="studen" parameterType="list">
select * from studen
<where>
<foreach collection="list" open="id in(" close=")" separator="," item="id">
#{id}
</foreach>
</where>
</select>
16. SQL 片段抽取
将一些重复性的SQL语句进行抽取 达到复用的效果
<sql>
标签 抽取sql语句标签 id属性唯一标识<include>
引入sql片段标签 refid属性需要引用片段的唯一标识
<sql id="select">select * from studen</sql>
<select id="qsq" resultType="student" parameterType="student">
<include refid="select"></include> where id = #{id}
</select>
17. 获取自增的ID 再插入数据
先执行LAST_INSERT_ID() 返回一个id并封装在对象 再执行inser语句
<insert id="add" parameterType="com.itheima.pojo.CheckGroup">
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
select LAST_INSERT_ID()
</selectKey>
insert into t_checkgroup(code, name, sex, helpCode, remark, attention)
values (#{code}, #{name}, #{sex}, #{helpCode}, #{remark}, #{attention})
</insert>
18. 分页插件
mybatis不带分页功能的 mysql中分页使用 limit 语句 不同的数据库实现的关键字也不同
PageHelper 第三方分页助手
导入jar包 pagehelper.jar jsqlparser.jar
在核心配置文件中集成分页助手
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
在测试类中使用分页功能
PageHelper.startPage(1,3);
// PageHelper.startPage(第几页,每页显示多少个); 设置分页参数
18.1. Pageinfo 封装分页相关参数的功能类
- getTotal() 获取总条数
- getPages() 获取总页数
- getPageNum() 获取当前页
- getPageSize() 获取每页显示条数
- getPrePage() 获取上一页
- getNextPage() 获取下一页
- islsFiresPage() 获取是否是第一页
- islsLastPage() 获取是否是最后一页
PageInfo<Student> info =new PageInfo<>(list);
int total = info.getTotal();
19. 多表操作
19.1. 一对一
<mapper namespace="1v1">
<!--
resultMap 配置字段和实体对象属性的映射关系
id为唯一标识
type为映射对象路径
-->
<resultMap id="oneToOne" type="card">
<!--
id为主键标签 column为表中列名 property为对象属性名称
result为其他列标签
-->
<id column="cid" property="id"/>
<result column="number" property="number" />
<!--
association: 配置被包含对象的映射关系 对象内的对象
property: 被包含对象的变量名 对象内的对象变量名是什么
javaType:被包含对象的数据类型
-->
<association property="prs" javaType="person">
<id column="pid" property="id"></id>
<result column="name" property="name"/>
<result column="age" property="age"/>
</association>
</resultMap>
<!--
resultMap 为多表操作映射
-->
<select id="selectall" resultMap="oneToOne">
select c.id cid,number,pid,name,age from card c,person p where c.pid=p.id;
</select>
</mapper>
<resultMap>
配置字段和实体对象属性的映射关系- id属性 唯一标识
- type属性 实体对象类型
<id>
配置主键映射关系标签<result>
配置非主键映射关系标签- column属性 表中字段名称
- property属性 实体对象变量名称
<association>
配置被包含对象的映射关系标签- property属性 被包含对象的变量名
- javaType属性 被包含对象的数据类型
19.2. 一对多
<mapper>
<resultMap id="onetomany" type="classes">
<id column="cid" property="id"/>
<result column="canem" property="name"/>
<!--
collection: 配置被包含的集合对象映射关系
property属性 被包含集合对象的变量名
ofType属性 被包含集合对象元素的数据类型
-->
<collection property="students" ofType="student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age"/>
</collection>
</resultMap>
<select id="selectall" resultMap="onetomany">
select c.id cid,c.name cname,s.id sid,s.name sname,s.age sage from classes c,student s where c.id=s.id
</select>
</mapper>
<collection>
配置被包含的集合对象映射关系- property属性 被包含集合对象的变量名
- ofType属性 被包含集合对象元素的数据类型
19.3. 多对多
<mapper>
<resultMap id="manytomany" type="sstdent">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age"/>
<collection property="coures" ofType="corse">
<id column="cid" property="id"/>
<result column="cname" property="name"/>
</collection>
</resultMap>
<select id="selectall" resultMap="manytomany">
select sc.sid,s.name sname,s.age sage,sc.cid,c.name cname from stdent s,course c,stu,_cr sc where sc.sid=s.id and sc.cid=c.id
</select>
</mapper>
<collection>
配置被包含的集合对象映射关系
- property属性 被包含集合对象的变量名
- ofType属性 被包含集合对象元素的数据类型
20. 注解
- @Select(“查询的SQL语句”) 指定参数还是#{key}
- @Insert(“新增的SQL语句”) 如:@Insert(“inser into student value (#{id},#{age},#{name})”)
- @Update(“修改的SQL语句”)
- @Delete(“删除的SQL语句”)
通过注解形式的操作 不需要创建映射配置文件 映射配置内容 写在核心配置文件中
<mappers>
<!-- name为接口所在的包路径 可以指定类或者指定包下的所有类 -->
<package name="com.xxx.xxx.stdentmapper"/>
</mappers>
19. 多表操作
19.1. 一对一
@Select("select * fome card")
@Results({
@Result(column = "id" ,property = "id"),
@Result(column = "number" , property = "number"),
@Result(
property = "p", // 被包含对象的变量名
javaType = Person.class, // 被包含对象的实现数据类型类
column = "pid", // 根据上面select查询出来表中的哪个字段来查询第二个表
/*
one = @one() 一对一写法
select属性 指定调用哪个接口的哪个方法
*/
one = @One(select = "com.xxx.xxx接口.selectByid方法")
)
})
List<Card> selectAll();
//@one注解调用的接口方法
@Select("select * from person where id=#{id}")
Person selectByid(Integer id);
@Results 封装映射关系的父注解 Result[] vlue() 定义了Result数组
@Result 封装映射关系的子注解
- column属性 查询出的表中字段名称
- property属性 实体对象中的属性名称
- javaType属性 被包含对象的数据类型
one 属性 一对一查询
@One一对一查询注解
- select属性 指向要调用某个接口中的方法
19.2. 一对多
//一对多
@Select("select * fome classes")
@Results({
@Result(column = "id" ,property = "id"),
@Result(column = "number" , property = "number"),
@Result(
property = "students", // 被包含对象的变量名
javaType = List.class, // 被包含对象的实现数据类型类
column = "id", // 根据上面select查询出来表中的哪个字段来查询第二个表
/* many = @Many() 一对多写法
select属性 指定调用哪个接口的哪个方法*/
many= @Many(select = "com.xxx.xxx接口.xxx方法")
)
})
List<Classes> selectAll();
//@one注解调用的接口方法
@Select("select * from student where cid=#{cid}")
List<Student> selectByid(Integer cid);
many属性 一对多查询
@Many一对多查询注解
- select属性 指向要调用某个接口中的方法
19.3. 多对多
//多对多
@Select("select distinct s.id,s.name fome studebt s,stu_cr sc where sc.sid = s.id")
@Results({
@Result(column = "id" ,property = "id"),
@Result(column = "number" , property = "number"),
@Result(
property = "students", // 被包含对象的变量名
javaType = List.class, // 被包含对象的实现数据类型类
column = "id", // 根据上面select查询出来表中的哪个字段来查询第二个表
/* many = @Many() 一对多写法
select属性 指定调用哪个接口的哪个方法*/
many= @Many(select = "com.xxx.xxx接口.xxx方法")
)
})
List<Student> selectAll();
//@one注解调用的接口方法
@Select("select c.id,c.name from stu_cr sc,course c where sc.cid=c.id and sc.sid=#{id}")
List<Course> selectByid(Integer id);
many属性 一对多查询
@Many一对多查询注解
- select属性 指向要调用某个接口中的方法
21. SQL 构建
public static void main(String[] args) {
System.out.println(getSelectall());
//SELECT *
//FROM student
}
public static String getSelectall(){
return new SQL(){
{
SELECT("*");
FROM("student");
}
}.toString();
}
@SelectProvider(type = SQL构造的类.class , mehod = “要执行类中方法”) 查询
@InsertProvider((type = SQL构造的类.class , mehod = “要执行类中方法”) 新增
public static String getInsert(Student stu){
return new SQL(){
{
INSERT_INTO("student");
INTO_VALUES("#{id},#{age},#{name}");
}
}.toString();
}
@UpdateProvider((type = SQL构造的类.class , mehod = “要执行类中方法”) 更新
@DeleteProvider((type = SQL构造的类.class , mehod = “要执行类中方法”) 删除