36-Mybatis-qianfeng-笔记
一、MyBatis简介
①:框架概念
框架,就是软件的半成品,完成了软件开发过程中的通用操作,程序员只需很少或者不用进行加工就能够实 现特定的功能,从而简化开发人员在软件开发中的步骤,提高开发效率。
②:常用框架
MWC框架:简化了Servlet的开发步骤
持久层框架:完成数据库操作的框架
apache DBUtils Hibernate Spring JPA MyBatis
胶水框架:Spring
SSM Spring SpringMVC MyBatis SSH Spring Struts2 Hibernate
③:MyBatis介绍
MyBatis.是一个半自动
的ORM
框架 ORM
(Object Relational Mapping)对象关系映射,将Java中的一个对象与数据表中一行记录一对应。 QRM
框架提供了实体类与数据表的映射关系,通过映射文件的配置,实现对象的持久化。
MyBatis
的前身是iBatis
,iBatis是Apache软件基金会提供的一个开源项目2010年iBatisi迁移到Google code
,正式更名为MyBatis 2013年迁移到Github托管 MyBatis
特点:
支持自定义SQL、存储过程 对原有的JDBC进行了封装,几乎消除了所有DBC代码,让开发者只需关注SQL本身 支持XML和注解配置方式自定完成ORM操作,实现结果映射
二、MyBatis框架部署
框架部署,就是将框架引入到我们的项目中
①:创建Maven项目
两者创建一个就可以了
②:在项目中添加MyBatis依赖
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
< version> 5.1.47</ version>
</ dependency>
< dependency>
< groupId> org.mybatis</ groupId>
< artifactId> mybatis</ artifactId>
< version> 3.4.6</ version>
</ dependency>
③:创建MyBatis配置文件(模板文件)
MyBatis-config.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>
</ configuration>
< environments default = " mysql" >
< environment id = " mysql" >
< transactionManager type = " JDBC" > </ transactionManager>
< dataSource type = " POOLED" >
< property name = " driver" value = " com.mysql.jdbc.Driver" />
< property name = " url" value = " jdbc:mysql://localhost:3306/db_fmwy?characterEncoding=utf-8" />
< property name = " username" value = " root" />
< property name = " password" value = " root" />
</ dataSource>
</ environment>
在mybatis-config.xml问及只能中配置数据库连接信息
三、MyBatis框架的使用
①:创建数据库
create table db_student(
sid int primary key auto_increment ,
stu_num char ( 5 ) not null unique ,
stu_name varchar ( 20 ) not null ,
stu_gender char ( 2 ) not null ,
stu_age int not null
) ;
tb_student表
②:安装lombok插件导入Lombok坐标
导入lombok
坐标
< dependency>
< groupId> org.projectlombok</ groupId>
< artifactId> lombok</ artifactId>
< version> 1.18.12</ version>
< scope> provided</ scope>
</ dependency>
安装lombok插件
③:创建实体类
@Data : 注在类上,提供类的get、set、equals、hashCode、toString等方法 @AllArgsConstructor :注在类上,提供类的全参构造 @NoArgsConstructor :注在类上,提供类的无参构造 @Setter :注在属性上,提供 set 方法 @Getter :注在属性上,提供 get 方法 @EqualsAndHashCode :注在类上,提供对应的 equals 和 hashCode 方法 @Log4j/@Slf4j :注在类上,提供对应的 Logger 对象,变量名为 log
Student.java
④:创建DAO接口,定义操作方法
StudentDAO.java
⑤:创建DAO接口的映射文件(Mapper)
<?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 = " " >
</ mapper>
1. 创建模板
2. 在resources
月录下,新建名为mappers
文件夹 在mappers
中新建名为StudentMapper,xml
的映射文件(根据模板创建)
3. 在映射问价中对DAO中定义的方法进行实现
public interface StudentDAO {
public int insertStudent ( Student student) ;
public int deleteStudent ( String stuNum) ;
}
<?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 = " com.it.dao.StudentDAO" >
< insert id = " insertStudent" >
insert into db_student(stu_num, stu_name, stu_gender, stu_age)
VALUES (#{stuNum},#{stuName},#{stu_Gender},#{stuAge})
</ insert>
< delete id = " deleteStudent" >
delete from db_student where stu_num=#{stuNum}
</ delete>
</ mapper>
4.将映射文件添加到主配置问价
四、单元测试
①:添加单元测试依赖
添加Junit依赖
< dependency>
< groupId> junit</ groupId>
< artifactId> junit</ artifactId>
< version> 4.12</ version>
< scope> test</ scope>
</ dependency>
②:创建单元测试类
1.在被测试类名后alt+insert-选择Create Test
③:测试代码
@Test
public void insertStudent ( ) {
try {
InputStream is = Resources . getResourceAsStream ( "mybatis-config.xml" ) ;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder ( ) ;
SqlSessionFactory factory = builder. build ( is) ;
SqlSession sqlSession = factory. openSession ( ) ;
StudentDAO studentDAO = sqlSession. getMapper ( StudentDAO . class ) ;
int i = studentDAO. insertStudent ( new Student ( 0 , "10001" , "张三" , "男" , 21 ) ) ;
sqlSession. commit ( ) ;
System . out. println ( i) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
五、MyBatis的CRUD操作
①:添加操作
略~可以参考上面的添加操作
②:删除操作
根据学号删除一条学生信息
1. 在StudentDAO中定义删除方法
2. 测试:在StudentDAO的测试类中添加测试方法
@Test
public void deleteStudent ( ) {
try {
InputStream is = Resources . getResourceAsStream ( "mybatis-config.xml" ) ;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder ( ) ;
SqlSessionFactory factory = builder. build ( is) ;
SqlSession sqlSession = factory. openSession ( ) ;
StudentDAO studentDAO = sqlSession. getMapper ( StudentDAO . class ) ;
int i = studentDAO. deleteStudent ( "10001" ) ;
sqlSession. commit ( ) ;
System . out. println ( i) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
}
③:修改操作
根据学生学号,修改其他字段信息
1. 在StudentDAO中添加修改方法
2. 在StudentMapper.xml文件中新增修改sql语句
3.添加单元测试方法
@Test
public void testUpdateStudent ( ) {
try {
InputStream is = Resources . getResourceAsStream ( "mybatis-config.xml" ) ;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder ( ) ;
SqlSessionFactory factory = builder. build ( is) ;
SqlSession sqlSession = factory. openSession ( ) ;
StudentDAO studentDAO = sqlSession. getMapper ( StudentDAO . class ) ;
int i = studentDAO. updateStudent ( new Student ( 0 , "10001" , "李四" , "♂" , 18 ) ) ;
sqlSession. commit ( ) ;
assertEquals ( 1 , i) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
4. 运行测试代码
④:查询所有
1. 先在数据库中添加一些信息
01.查询方法一
1.在StudentDAO接口中定义方法
2. StudentMapper.xml问价中添加sql语句
3. 测试代码
@Test
public void testSelectStudent ( ) {
try {
InputStream is = Resources . getResourceAsStream ( "mybatis-config.xml" ) ;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder ( ) ;
SqlSessionFactory function = builder. build ( is) ;
SqlSession sqlSession = function. openSession ( ) ;
StudentDAO studentDAO = sqlSession. getMapper ( StudentDAO . class ) ;
List < Student > studentList = studentDAO. selectStudent ( ) ;
for ( Student s : studentList) {
System . out. println ( s) ;
}
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
02.查询方式二
1. 只修改StudentMapper.xml中的sql语句即可
⑤:根据主键查询一条信息
1. StudentDAO接口中定义方法
2. StudentMapper.xml问价中定义sql语句
3. 单元测试代码
@Test
public void testQueryStudent ( ) {
try {
InputStream is = Resources . getResourceAsStream ( "mybatis-config.xml" ) ;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder ( ) ;
SqlSessionFactory function = builder. build ( is) ;
SqlSession sqlSession = function. openSession ( ) ;
StudentDAO studentDAO = sqlSession. getMapper ( StudentDAO . class ) ;
Student student = studentDAO. queryStudent ( "10001" ) ;
System . out. println ( student) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
⑥:分页查询-多个参数
01.方法一(arg0,arg1)
1. StudentDAO接口中定义方法
2. StudentMapper.xml问价中定义sql语句
3. 单元测试代码
02.方法二 (使用HashMap)
1. StudentDAO接口中定义方法
2. StudentMapper.xml问价中定义sql语句
3. 单元测试代码
03.方法三(使用@Param注解)
1. StudentDAO接口中定义方法
2. StudentMapper.xml问价中定义sql语句
3. 单元测试代码
⑦:查询总记录数(返回int)
1. StudentDAO接口中定义方法
2.在StudentMapper.xmlg配置sql,通过resultType指定当前操作的返回类型为int
3. 单元测试代码
⑧:添加操作回填生成的主键
StudentDAO接口中定义添加方法(之前已经完成)
2.在StudentMapper.xmlg配置sql
3. 单元测试代码
六、MyBatis工具类
package com. it. utils ;
import org. apache. ibatis. io. Resources ;
import org. apache. ibatis. session. SqlSession ;
import org. apache. ibatis. session. SqlSessionFactory ;
import org. apache. ibatis. session. SqlSessionFactoryBuilder ;
import java. io. IOException ;
import java. io. InputStream ;
public class MyBatisUtil {
private static SqlSessionFactory factory;
private static final ThreadLocal < SqlSession > local = new ThreadLocal < SqlSession > ( ) ;
static {
try {
InputStream is = Resources . getResourceAsStream ( "mybatis-config.xml" ) ;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder ( ) ;
factory = builder. build ( is) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public static SqlSessionFactory getFactory ( ) {
return factory;
}
public static SqlSession getSqlSession ( ) {
SqlSession sqlSession = local. get ( ) ;
if ( sqlSession == null ) {
sqlSession = factory. openSession ( ) ;
local. set ( sqlSession) ;
}
return sqlSession;
}
public static < T > T getMapper ( Class < T > clas) {
SqlSession sqlSession = getSqlSession ( ) ;
return sqlSession. getMapper ( clas) ;
}
}
七、事务管理
SqlSession对象
getMapper(DAQ.class)):获取Mapper(DAQ接口的实例) 事务管理
①:手动提交事务
sqlSession.commit();
提交事务sqlSession.rol1back();
事务▣滚
@Test
public void testUpdateStudent ( ) {
SqlSession sqlSession = myBatisUtil. getSqlSession ( ) ;
try {
StudentDAO studentDAO = sqlSession. getMapper ( StudentDAO . class ) ;
int i = studentDAO. updateStudent ( new Student ( 0 , "10001" , "李四" , "♂" , 18 ) ) ;
sqlSession. commit ( ) ;
assertEquals ( 1 , i) ;
} catch ( Exception e) {
sqlSession. rollback ( ) ;
}
}
②:自动提交事务
通过SqlSessionFactoryi调用openSession方法获取SqlSession对象时,可以通过参数设置事务是香自动提交:
如果参数设置为true,表示自定提交事务:factory.openSession(true: 如果参数设置为false,或者不设置参数,表示手动提交:factory.openSession0;/factory…openSession(false);
MyBatisUTil代码优化
package com. it. utils ;
import org. apache. ibatis. io. Resources ;
import org. apache. ibatis. session. SqlSession ;
import org. apache. ibatis. session. SqlSessionFactory ;
import org. apache. ibatis. session. SqlSessionFactoryBuilder ;
import java. io. IOException ;
import java. io. InputStream ;
public class MyBatisUtil {
private static SqlSessionFactory factory;
private static final ThreadLocal < SqlSession > local = new ThreadLocal < SqlSession > ( ) ;
static {
try {
InputStream is = Resources . getResourceAsStream ( "mybatis-config.xml" ) ;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder ( ) ;
factory = builder. build ( is) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public static SqlSessionFactory getFactory ( ) {
return factory;
}
public static SqlSession getSqlSession ( boolean isAutoCommit) {
SqlSession sqlSession = local. get ( ) ;
if ( sqlSession == null ) {
sqlSession = factory. openSession ( isAutoCommit) ;
local. set ( sqlSession) ;
}
return sqlSession;
}
public static < T > T getMapper ( Class < T > clas) {
SqlSession sqlSession = getSqlSession ( true ) ;
return sqlSession. getMapper ( clas) ;
}
}
测试代码(举例)
@Test
public void testUpdateStudent ( ) {
SqlSession sqlSession = myBatisUtil. getSqlSession ( true ) ;
try {
StudentDAO studentDAO = sqlSession. getMapper ( StudentDAO . class ) ;
int i = studentDAO. updateStudent ( new Student ( 0 , "10001" , "李四" , "♂" , 18 ) ) ;
sqlSession. commit ( ) ;
assertEquals ( 1 , i) ;
} catch ( Exception e) {
sqlSession. rollback ( ) ;
}
}
@Test
public void testSelectStudent ( ) {
MyBatisUtil myBatisUtil = new MyBatisUtil ( ) ;
StudentDAO studentDAO = myBatisUtil. getMapper ( StudentDAO . class ) ;
List < Student > studentList = studentDAO. selectStudent ( ) ;
for ( Student s : studentList) {
System . out. println ( s) ;
}
}
八、MyBatis主配置文件
①:properties标签
用于设置键值对,或者加载属性文件
1. 在resources目录下创建jdbc.proper1es`文件,配置键值对如下:
mysql_driver= com. mysql. jdbc. Driver
mysql_url= jdbc: mysql: / / localhost: 3306 / db_mybatis_demo1? characterEncoding= utf- 8
mysql_username= root
mysql_password= root
2. 在mybatis-config,.xml中通过properties标签引用jdbc.properties文件; 引入之后,在配置environment时可以直接使用id地C.properties的key获取对应的value
3.代码测试
②:settings标签
< settings>
< setting name = " cacheEnabled" value = " true" />
< setting name = " lazyLoadingEnabled" value = " true" />
</ settings>
③:typeAliases标签
< typeAliases>
< typeAlias type = " com.it.pojo.Student" alias = " Student" > </ typeAlias>
</ typeAliases>
在映射文件中可以直接使用别名来替代实体类的全限定名
④:plugins标签
< plugins>
< plugin interceptor = " " > </ plugin>
</ plugins>
⑤:environments标签
< environments default = " mysql" >
< environment id = " mysql" >
< transactionManager type = " JDBC" > </ transactionManager>
< dataSource type = " POOLED" >
< property name = " driver" value = " ${mysql_driver}" />
< property name = " url" value = " ${mysql_url}" />
< property name = " username" value = " ${mysql_username}" />
< property name = " password" value = " ${mysql_password}" />
</ dataSource>
</ environment>
</ environments>
⑥:mapper标签
< mappers>
< mapper resource = " mappers/StudentMapper.xml" > </ mapper>
</ mappers>
九、映射文件
①:MyBatis Mapper初始化
②:Mapper根标签
mapper3文件相当于DAQ接口的‘实现类’,amespacel属性要指定实现DAQ接口的全限定名
③:insert标签
声明添加操作(sql:insert) 常用属性
id属性
,绑定对应DAQ接口中的方法parameterType
属性,用以指定接口中对应方法的参数类型(可省略)useGeneratedKeys
属性,设置添加操作是否需要回填生成的主键 keyProperty
属性,指定回填的id设置到参数对象中的哪个属性timeout
属性,设置此操作的超时时间,如果不设置则一直等待
主键回填
< insert id = " insertStudent" useGeneratedKeys = " true" keyProperty = " stuId" >
insert into db_student(stu_num, stu_name, stu_gender, stu_age)
VALUES (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
</ insert>
< insert id = " insertStudent" >
< selectKey keyProperty = " stuId" resultType = " java.lang.Integer" >
select last_insert_id()
</ selectKey>
insert into db_student(stu_num, stu_name, stu_gender, stu_age)
VALUES (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
</ insert>
④:delete标签
声明删除操作
< delete id = " deleteStudent" >
delete
from db_student
where stu_num = #{stuNum}
</ delete>
⑤:update标签
声明修改操作
< update id = " updateStudent" >
update db_student
set stu_name=#{stuName},
stu_gender=#{stuGender},
stu_age=#{stuAge}
where stu_num = #{stuNum}
</ update>
⑥:select标签
声明查询操作
id
属性,指定绑定方法的方法名parameterType
属性,设置参数类型resultType
属性,指定当前sq返回数据封装的对象类型(实体类)resultMap
属性,指定从数据表到实体类的字段和属性的对应关系useCache
属性,指定此查询操作是否需要缓存timeout
属性,设置超时时间
< select id = " selectStudent" resultType = " com.it.pojo.Student" resultSets = " java.util.List" >
select stu_num stuNum, stu_name stuName, stu_gender stuGender, stu_age stuAge
from db_student
</ select>
< resultMap id = " studentMap" type = " Student" >
< id column = " sid" property = " stuId" />
< result column = " stu_num" property = " stuNum" />
< result column = " stu_name" property = " stuName" />
< result column = " stu_gender" property = " stuGender" />
< result column = " stu_age" property = " stuAge" />
</ resultMap>
< select id = " selectStudent" resultMap = " studentMap" >
select stu_num, stu_name, stu_gender, stu_age
from db_student
</ select>
⑦:resultMap标签
< resultMap id = " studentMap" type = " Student" >
< id column = " sid" property = " stuId" />
< result column = " stu_num" property = " stuNum" />
< result column = " stu_name" property = " stuName" />
< result column = " stu_gender" property = " stuGender" />
< result column = " stu_age" property = " stuAge" />
</ resultMap>
⑧:cache标签
设置当前DAQ进行数据库操作时的缓存属性设置
< cache type = " " size = " " readonly = " false" />
⑨:sql片段和include
十、分页插件
分页插件是一个独立于MyBatis框架之外的第三方插件;
①:添加分页插件的依赖
PageHelper
< ! -- pagehelper分页插件 -- >
< dependency>
< groupId> com. github. pagehelper< / groupId>
< artifactId> pagehelper< / artifactId>
< version> 5.2 .0 < / version>
< / dependency>
②:配置插件
在mybatisl的主配置文件mybatis-config.xml中通过plugins标签进行配置
< plugins>
< plugin interceptor = " com.github.pagehelper.PageInterceptor" > </ plugin>
</ plugins>
③:分页实例
01.不带条件分页
对学生信息进行分页查询
@Test
public void testSelectStudentByPage2 ( ) {
StudentDAO studentDAO = myBatisUtil. getMapper ( StudentDAO . class ) ;
PageHelper . startPage ( 1 , 3 ) ;
List < Student > studentList = studentDAO. selectStudent ( ) ;
PageInfo < Student > pageInfo = new PageInfo < Student > ( studentList) ;
List < Student > list = pageInfo. getList ( ) ;
for ( Student student : list) {
System . out. println ( student) ;
}
02.带条件分页
1. 在StudentDAO中定义接口方法
2.在StudentMapper中定义SQl语句
3. 测试代码
@Test
public void testSelectStudentByGender ( ) {
StudentDAO studentDAO = myBatisUtil. getMapper ( StudentDAO . class ) ;
PageHelper . startPage ( 1 , 5 ) ;
List < Student > studentList = studentDAO. selectStudentByGender ( "♂" ) ;
PageInfo < Student > pageInfo = new PageInfo < Student > ( studentList) ;
List < Student > list = pageInfo. getList ( ) ;
for ( Student student : list) {
System . out. println ( student) ;
}
}
十一、关联映射
①:实体关系
实体一一数据实体,实体关系指的就是数据与数据之间的关系 例如:用户和角色、房屋和楼栋、订单和商品
实体关系分为以下四种:
一对一关联
实例:人和身份证、学生和学生证、用户基本信息和详情
数据表关系:
主键关联(用户表主键和详情主键相同时,表示是匹配的数据
唯一外键关联
一对多关联、多对一关联
实例:
一对多:班级和学生、类别和商品 多对一:学生和班级、商品和类别
数据表关系:
多对多关联
实例:用户和角色、角色和权限、房屋和业主、学生和社团、订单和商品
数据库关系 :
建立第三张关系表添加两个外键分别与两张表主键进行关联 用户(user_id) 用户角色表uid,rid) 角色(role_id)
②:创建项目,部署MyBatis框架
创建web项目(Maven)
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> jsp-api</ artifactId>
< version> 2.0</ version>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> javax.servlet-api</ artifactId>
< version> 4.0.1</ version>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> org.mybatis</ groupId>
< artifactId> mybatis</ artifactId>
< version> 3.4.6</ version>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
< version> 5.1.47</ version>
</ dependency>
driver= com. mysql. jdbc. Driver
url= jdbc: mysql: / / localhost: 3306 / db_mybatis? characterEncoding= utf- 8
username= root
password= root
创建mybatis-config.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>
< properties resource = " jdbc.properties" />
< environments default = " mysql" >
< environment id = " mysql" >
< transactionManager type = " JDBC" > </ transactionManager>
< dataSource type = " POOLED" >
< property name = " driver" value = " ${driver}" />
< property name = " url" value = " ${url}" />
< property name = " username" value = " ${username}" />
< property name = " password" value = " ${password}" />
</ dataSource>
</ environment>
</ environments>
</ configuration>
public class MyBatisUtil {
private static SqlSessionFactory factory;
private static ThreadLocal < SqlSession > local = new ThreadLocal < SqlSession > ( ) ;
static {
try {
InputStream is = Resources . getResourceAsStream ( "mybatis-config.xml" ) ;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder ( ) ;
factory = builder. build ( is) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public static SqlSessionFactory getSqlSessionFactory ( ) {
return factory;
}
public static SqlSession getSession ( boolean isAutoCommit) {
SqlSession sqlSession = local. get ( ) ;
if ( sqlSession == null ) {
sqlSession = factory. openSession ( isAutoCommit) ;
local. set ( sqlSession) ;
}
return sqlSession;
}
public static SqlSession getSession ( ) {
return getSession ( false ) ;
}
public static < T > T getMapper ( Class < T > clazz) {
SqlSession session = getSession ( true ) ;
return session. getMapper ( clazz) ;
}
}
③:一对一关联添加操作
01.创建数据库
实例:用户-----详情
create table users(
user_id int primary key auto_increment ,
user_name varchar ( 20 ) not null unique ,
user_pwd varchar ( 30 ) not null ,
user_realname varchar ( 30 ) not null ,
user_img varchar ( 100 ) not null
) ;
create table details(
detail_id int primary key auto_increment ,
user_addr varchar ( 50 ) not null ,
user_tel char ( 11 ) not null ,
user_desc varchar ( 200 ) ,
uid int not null unique
) ;
02.创建实体类
导入lombok依赖(使用注解@Data不用写 get set 方法)
< dependency>
< groupId> org.projectlombok</ groupId>
< artifactId> lombok</ artifactId>
< version> 1.18.24</ version>
< scope> provided</ scope>
</ dependency>
03.一对一添加操作 1
1. 在接口中定义方法
2. UserMapper中添加Sql语句
3.在MyBatis-config.xml中添加映射关系
4.测试代码
04.一对一添加操作 2
1. 在DetailDAO接口中定义方法
2. 在DetailMapper.xml文件中添加sql方法
3. 在mybatis-config.xml中添加映射关系
4. 测试代码
④:一对一关联查询操作
01. 单表查询(查询User用户信息)
1. 在UserDAO接口中定义查询方法
2. 在mybatis-config.xml文件中给DAO类起别名方便后续使用
3. 在UserMapper文件中添加查询Sql语句
4. 测试代码
02.两个表关联查询
1. 关联查询方案1(连接查询)
1. UserDao接口中定义方法
2. 在User类中加入detail属性
< select id = " queryUserAndDetailByName" resultMap = " userMap" >
select user_id, user_name, user_pwd, user_realname, user_img,detail_id, user_addr, user_tel, user_desc
from users u
join details d on u.user_id = d.uid
where user_name = #{userName};
</ select>
4. 在resultMap中添加detail属性映射关系
5. 测试代码
2.关联查询方案2(子查询)
1. 分别在UserDao和DetailDAO中定义接口方法
2. 分别在UserMapper和DetailMapper文件中添加sql语句
3. 测试代码
⑤:一对多关联查询
案例:班级(1)—> 学生(n)
01. 创建数据表
create table classes(
cid int primary key auto_increment ,
cname varchar ( 30 ) not null unique ,
cdesc varchar ( 100 )
) ;
create table students(
sid char ( 5 ) primary key ,
sname varchar ( 28 ) not null ,
sage int not null ,
scid int not null
) ;
02.创建实体类
Class班级类 student学生类
03.一对多关联查询
查询一个班级要关联查询出该班级下的所有学生
1. 添加数据
class班级表 student学生表
2.关联查询方式一(连接查询)
1. 创建ClazzDAO接口定义接口方法
2. 添加Mapper并起别名
3. 在ClazzMapper文件中添加Sql语句
4. 测试代码
3.关联查询方式二(子查询)
1.在ClazzDAO中定义接口方法 在StudentDAO中定义接口方法
2. 在mybatis-config.xml文件中添加映射关系
3.分别在ClazzMapper和StudentMapper文件中添加Sql语句
4. 测试代码
⑥:多对一关联查询
01.创建实体类
Students2 Clazz2
02.关联查询方式一(连接查询)
1. 定义接口方法
2. 创建Students2Mapper文件并在mybatis-config文件中进行关联
3. 在Student2Mapper文件中添加Sql语句
4. 测试代码
03. 关联查询方式二(子查询)
1. 分别在Student2DAO和Clazz2DAO接口中定义方法
2. 创建Clazz2Mapper文件并在mybatis-config文件中进行关联
3. 分别在Clazz2Mapper.xml和Student2Mapper.xml文件中添加Sql语句
4. 测试代码
⑦:多对多关联查询
案例:学生(m)—> 课程(n)
01.创建数据表
create table courses(
course_id int primary key auto_increment ,
course_name varchar ( 50 ) not null
) ;
create table grades(
sid char ( 5 ) not null ,
cid int not null ,
score int not null
) ;
添加数据
02.关联查询方式一(连接查询)
根据课程名称查询课程时,同时查询选择了这门课的学生
1. 创建实体类
2. 在CourseDAO添加接口方法
3. 创建CourseMapper.xml文件并在mybatis-config.xml文件中添加关联关系
4. CourseMapper.xml文件中添加Sql语句
5. 测试代码
03.关联查询方式二(子查询)
1. 分别在StudentDAO和CourseDAO中定义接口方法
2. 分别在StudentMapper.xml和CourseMapper.xml中添加语句
3. 测试代码
十二、动态SQL
①:什么时动态SQL?
根据查询条件动态完成SQL的拼接
②:动态SQL使用案例
案例:心仪对象搜索
01.创建项目
步骤略~ 可以参考上面的
02.创建数据表
create table members(
member_id int primary key auto_increment ,
member_nick varchar ( 20 ) not null unique ,
member_gender char ( 2 ) not null ,
member_age int not null ,
member_city varchar ( 30 ) not null
) ;
03. 创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Member {
private int memberId;
private String memberNick;
private String memberGender;
private int memberAge;
private String memberCity;
}
03.添加数据
③:动态SQL实现1(if)
1. 创建MemberDAO接口并定义接口方法
2. 创建MemberMapper.xml文件并在mybatis-config.xml文件中关联
3. 在MemberMapper.xml文件中添加SQl语句
4. 测试代码
④:动态SQL实现2(where)
01. 使用<where>
标签
1. 使用方法
2. 查询的结果还是一样的
02.使用<trim>
标签
1. 使用方法
2. 查询结果
03.<foreach>
标签的使用
1. 定义接口方法
2. 在MemberMapper文件中添加SQL语句
3. 测试代码
04 <if>标签
嵌入<foreach>
标签
1. 在MemberDAO中添加接口方法
2. 定义SQL语句
3. 测试代码
十三、模糊查询
//根据昵称查询用户信息--模糊查询
//模糊查询需要使用${}取值,与sq1进行拼接
//在使用${}时,即使只有一个参数也需要使用@Param注解声明参数的key(非String对象参数可以不用声明)
①: MemberDAO中定义接口方法
②:在MemberMapper中添加SQL语句
③:测试代码
④:#{}和${}的区别
S{key}表示获取参数,先获取参数的值拼接到SQL语句中,再编译执行SQL语句;可能引起SQL注入问题 #{ky}表示获取参数,先完成SQL编译(预编译),预编译之后再将获取的参数设置到SQL与中,可以避免SQL注入问题
十四、MyBatis日志配置
MyBatis做为一个封装好的QRM框架,其运行过程我们没办法跟踪,为了让开发者了解yBatis执行流程及每个执行步骤所完成的工作,MyBatis框架本身支持og4i日志框架,对运行的过程进行跟踪记录。我们只需对MyBatisi进行相关的日志配置,就可以看到MyBatisi运行过程中的日志信息。
①:添加日志框架依赖
< dependency>
< groupId> log4j</ groupId>
< artifactId> log4j</ artifactId>
< version> 1.2.17</ version>
</ dependency>
②:添加日志配置文件
在resources目录下创建名为 log4j.properties
文件(可以创建模板)
{.brush:xml;toolbar: .true; .auto-links: .false;}
log4j.rootLogger=DEBUG, INFO, ERROR
# 输出控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%p]%d{yyyy-MM-dd HH:mm:ss} %l - %m%n
详细日志控制台
# Global logging configuration
# 设置日志输出级别以及输出目的地,可以设置多个输出目的地,开发环境下,日志级别要设置成DEBUG或者ERROR
# 前面写日志级别,逗号后面写输出目的地:我自己下面设置的目的地相对应,以逗号分开
# log4j.rootLogger = [level],appenderName1,appenderName2,…
log4j.rootLogger=DEBUG,CONSOLE,LOGFILE
#### 控制台输出 ####
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
# 输出到控制台
log4j.appender.CONSOLE.Target = System.out
# 指定控制台输出日志级别
log4j.appender.CONSOLE.Threshold = DEBUG
# 默认值是 true, 表示是否立即输出
log4j.appender.CONSOLE.ImmediateFlush = true
# 设置编码方式
log4j.appender.CONSOLE.Encoding = UTF-8
# 日志输出布局
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
# 如果日志输出布局为PatternLayout 自定义级别,需要使用ConversionPattern指定输出格式
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p (%c:%L) - %m%n
#### 输出错误信息到文件 ####
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
# 指定输出文件路径
#log4j.appender.LOGFILE.File =F://Intellij idea/logs/error.log
log4j.appender.LOGFILE.File =./logs/error.log
#日志输出到文件,默认为true
log4j.appender.LOGFILE.Append = true
# 指定输出日志级别
log4j.appender.LOGFILE.Threshold = ERROR
# 是否立即输出,默认值是 true,
log4j.appender.LOGFILE.ImmediateFlush = true
# 设置编码方式
log4j.appender.LOGFILE.Encoding = UTF-8
# 日志输出布局
log4j.appender.LOGFILE.layout = org.apache.log4j.PatternLayout
# 如果日志输出布局为PatternLayout 自定义级别,需要使用ConversionPattern指定输出格式
log4j.appender.LOGFILE.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
③:日志信息的级别
级别 描述 ALL 所有级别包括自定义级别。 DEBUG 调试消息日志。 ERROR 错误消息日志,应用程序可以继续运行。 FATAL 严重错误消息日志,必须中止运行应用程序。 INFO 输出提示消息。 OFF 最高可能的排名,旨在关闭日志记录。 TRACE 高于DEBUG。 WARN 用于警告消息。
十五、整合Druid连接池
MyBatis做为一个ORM框架,在进行数据库操作时是需要和数据库连接池连接的,MyBatis支持基于数据库连接池的连接创建方式。 当我们配置MyBatis数据源时,只要配置了data Source标签的type属性值为POOLEDI时,就可以使用MyBatis内置的连接池管理连接。 如果我们想要使用第三方的数据库连接池,则需进行自定义配置。
①:常见的连接池
DBCP C3PO Druid性能也比较好,提供了比较便捷的监控系统 Hikari性能最好
功能 dbcp druid c3p0 tomcat-jdbc HikariCP 是否支持PSCache 是 是 是 否 否 监控 jmx jmx/log/http jmx,log jmx jmx 扩展性 弱 好 弱 弱 弱 sql拦截及解析 无 支持 无 无 无 代码 简单 中等 复杂 简单 简单 更新时间 2015.8.6 2015.10.10 2015.12.09 2015.12.3 特点 依赖于common-pool 阿里开源,功能全面 历史久远,代码逻辑复杂,且不易维护 优化力度大,功能简单,起源于boneCP 连接池管理 LinkedBlockingDeque 数组 FairBlockingQueue threadlocal+CopyOnWriteArrayList
②:添加Druid依赖
< dependency>
< groupId> com.alibaba</ groupId>
< artifactId> druid</ artifactId>
< version> 1.2.8</ version>
</ dependency>
③:将MyBatis的连接池替换为Druid
01. 创建Druid连接池工厂
public class DruidDataSourceFactory extends PooledDataSourceFactory {
public DruidDataSourceFactory ( ) {
this . dataSource = new DruidDataSource ( ) ;
}
}
02. 将DruidDataSourceFactory配置给MyBatis数据源
< environments default = " mysql" >
< environment id = " mysql" >
< transactionManager type = " JDBC" />
< dataSource type = " com.it.utils.DruidDataSourceFactory" >
< property name = " driverClass" value = " ${driver}" />
< property name = " jdbcUrl" value = " ${url}" />
< property name = " username" value = " ${username}" />
< property name = " password" value = " ${password}" />
</ dataSource>
</ environment>
</ environments>
十六、MyBatis缓存
MyBatis是基于DBC的封装,使数据库操作更加便捷;MyBatisl除了对JDBC操作步骤进行封装之外也对其性能进行了优化:
在MyBatis引入缓存机制,用于提升MyBatis的检索效率
①:缓存的工作原理
②:MyBatis缓存
MyBatis缓存分为一级缓存和二级缓存
01.一级缓存(特性一)
一 级缓存也叫做SqlSession级缓存,为每个SqlSession单独分配的缓存内存,无需手动开启可直接使用;多个SqlSessionl的缓存是不共享的。
1.如果多次查询使用的是同一个SqlSession对象,则第一次查询之后数据会存放到缓存,后续的查询则直接访问缓存中存储的数据:
1. 在MemberDAO中定义接口方法
2. MemberMapper.xml中添加SQL语句
3.测试代码(使用同一SqlSession)
4.测试代码(使用不同的SqlSession)
02.一级缓存(特性二)
2.如果第一次查询完成之后,对查询出的对象进行修改(此修改会影响到缓存),第二次查询会直接访问缓存,造成第二次查询的结果与数据库不一致;
03.一级缓存(特性三)
3.当我们进行在查询时想要跳过缓存直接查询数据库,则可以通过sqlSession…clearCache0;来清除当前SqlSession的缓存;
1. 进行缓存清除
04.一级缓存(特性四)
4.如果第一次查询之后第二查询之前,使用当前的sqlsession执行了修改操作,此修改操作会使第一次查询并缓存的数据失效,因此第二次查询会再次访问数据库。
1. 新增修改方法
2. 添加修改语句
3, 测试代码
③:一级缓存使用存在的问题(两次查询与数据库不一致)
④:二级缓存机制
二级缓存也称为SqlSessionFactory级缓存,通过同一个factory对象获取的Sqlsession可以共享二级缓存;在应 用服务器中SqlSessionFactory是单例的,因此我们二级缓存可以实现全局共享。 特性:
1.二级缓存默认没有开启,需要在mybatis-config,xml中的settings标签开启 2.二级缓存只能缓存实现序列化接口的对象
1. 在mybatis-config.xml文件中开启二级缓存
< settings>
< setting name = " cacheEnabled" value = " true" />
</ settings>
2. 在需要使用二级缓存的Mapper文件中配置cache标签使用功能二级缓存
< cache/>
3.使用二级缓存(被缓存的实体类实现序列化接口)
4. 测试代码1
(第一次查询,之后执行sqlSession1.commit(),会将当前sqlsession的查询结果缓存到二级缓存)
5. 测试代码2
⑤:设置每次修改或查询后自动刷新缓存
true:使用缓存 fase:不使用缓存
十七、延迟加载(只在子查询中生效)
延迟加载–如果在MyBatis开启了延迟加载,在执行了子查询(至少查询两次及以上)时,默认只执行第一次查询,当用到子查询的查询结果时,才会触发子查询的执行;如果无需使用子查询结果,则子查询不会执行。
①:使用子查询完成(班级–>学生)一对多查询
1.分别创建两个实体类(Student)(Clazz)
2. 创建两个实体类的Mapper文件并在mybatis-config文件中起别名等
3.在ClazzDAO中添加接口方法
4. 在ClazzMapper文件中添加Sql语句
5.在StudentDAO中添加接口方法
6在ClazzMapper文件中添加Sql语句
②:测试代码(不开启延迟加载)
1. 不开启延迟加载情况下只打印班级名称
③:测试代码(开启延迟加载)
1. 开启延迟加载
2.测试代码1(发现并没有去查询学生信息)
3.测试代码(查询学生信息)