MyBatis day01
1 MyBatis引言
MyBatis原名(iBatis),是一个持久层(dao)框架,提供了简便的操作数据库的功能(CRUD)。是对原生JDBC操作的封装,用来替换原生JDBC访问数据库。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8VrM1Qoq-1630934134602)(MyBatis day01.assets/image-20210604141244238.png)]
总结:MyBatis用于替换原生JDBC操作,解决原生JDBC的不足。
2 MyBatis的使用思路
MyBatis封装了原生的JDBC操作,在开发中用来替换原有的Dao实现方式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-upgFI1m1-1630934134607)(MyBatis day01.assets/image-20210604213732936.png)]
MyBatis是如何替换dao实现类?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t2GXtDuG-1630934134608)(MyBatis day01.assets/image-20210604215242673.png)]
XxxDaoMapper.xml
-
定义接口方法要执行的SQL语句
-
sql语句写在相应类型的标签中:
<insert></insert> <update></update> <delete></delete> <select></select>
-
每个标签中都有id属性,值必须为方法名,保证sql语句和方法的对应关系
3 第1个MyBatis程序
3.1 MyBatis中的配置文件
- log4j.properties
- 作用:开启log4j日志功能,用于分析程序运行的过程
- 位置: main/resources根目录下(规定)
- XxxDaoMapper.xml
- 作用:定义dao接口要执行的sql语句,用来替换dao实现类
- 位置:dao包下(规范)
- mybatis-config.xml
- 作用:对MyBatis框架进行基本的配置(数据库的用户名密码,mapper.xml的位置)
- 位置:main/resources根目录里(规范)
3.2 MyBatis中的常用API
-
Resources类:
- 资源:项目中除了代码外的部分
- 作用:方便读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml的路径");
-
SqlSession接口
作用:
-
通过sqlSession获取dao接口实现类对象
-
sqlSession内部封装了一个Connection,一一对应。
-
sqlSession可以控制事务
//sqlSession获取Dao实现类对象 UserDao userDao = sqlSession.getMapper(UserDao.class); //事务控制 sqlSession.commit();//提交事务 sqlSession.rollback();//回滚事务
-
-
SqlSessionFactory接口
作用:用来创建SqlSession对象。
SqlSession sqlSession = sqlSessionFactory.getSession();//获取sqlSession对象
3.3 MyBatis项目开发步骤
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wm3NBjaK-1630934134610)(MyBatis day01.assets/image-20210604220105758.png)]
MyBatis项目和JDBC项目的开发步骤整体流程相同,主要差别在Dao实现使用mapper.xml替换
3.4 实战
需求:查询user_id为2的用户信息
-
搭建开发环境
-
新建一个项目
-
导入jar包
pom.xml <!-- 声明依赖 --> <dependencies> <!-- 引入mybatis依赖 --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.30</version> </dependency> <!-- 引入数据库驱动依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <!-- 引入junit的依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies>
-
导入配置文件
- log4j.properties
- 作用:开启log4j日志功能,用于分析程序运行的过程
- 位置: main/resources根目录下(规定)
- XxxDaoMapper.xml
- 作用:定义dao接口要执行的sql语句,用来替换dao实现类
- 位置:dao包下(规范)
- mybatis-config.xml
- 作用:对MyBatis框架进行基本的配置(数据库的用户名密码,mapper.xml的位置)
- 位置:main/resources根目录里(规范)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3O7vof9n-1630934134611)(MyBatis day01.assets/image-20210602163539166.png)]
- log4j.properties
-
配置文件初始化(初始化mybatis-config.xml)
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> <!-- 配置数据库环境 environments下可以配置多个environment(数据库环境) --> <environments default="dev"> <environment id="dev"> <!-- 配置事务的管理方式: JDBC:必须手动管理 MANAGED:委托给第3方有事务管理能力的框架或者容器 --> <transactionManager type="JDBC"></transactionManager> <!-- 连接池: type: POOLED 使用连接池 UNPOOLED 不使用连接池 --> <dataSource type="POOLED"> <property name="driver" value="驱动类全类名"/> <property name="url" value="url值"/> <property name="username" value="用户名"/> <property name="password" value="密码"/> </dataSource> </environment> </environments> <!-- 配置mapper.xml的路径 --> <mappers> <mapper resource="mapper.xml的路径"/> </mappers> </configuration>
-
-
建表
create table t_user( user_id int primary key auto_increment, username varchar(20) not null unique, password varchar(40) not null );
-
实体类
public class User implements Serializable { private Integer userId; private String username; private String password; public User() { } public User(Integer userId, String username, String password) { this.userId = userId; this.username = username; this.password = password; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "userId=" + userId + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
-
dao
和之前一样定义接口,UserDao接口:
public interface UserDao { public User selectUserById(Integer id); }
在resources/com/baizhi/dao文件夹下创建UserDaoMapper.xml替换实现类.
UserDaoMapper.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" >
<!--
namespace:设置mapper.xml要绑定的接口全类名
-->
<mapper namespace="com.baizhi.dao.UserDao">
<select id="selectUserById" resultType="com.baizhi.entity.User">
select user_id as userId,user_name as username,password from t_user where user_id = #{id}
</select>
</mapper>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3pOrcfJI-1630934134612)(MyBatis day01.assets/image-20210602173637527.png)]
-
service(暂时省略)
-
test
UserDaoTest.java
public class UserDaoTest { @Test public void testSelectUserById() throws IOException { //1 读取配置文件 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); //2 创建SqlSessionFactory对象 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3 创建SqlSession对象 SqlSession sqlSession= factory.openSession(); //4 创建Dao接口实现类对象 UserDao dao = sqlSession.getMapper(UserDao.class); //5 调用方法 User u = dao.selectUserById(2); System.out.println("u="+u); //6 关闭sqlSession sqlSession.close(); } }
4 resultType属性
设置sql语句返回结果的类型:类型的全类名
4.1 方法返回值类型为List
方法返回值类型为List,resultType仍为实体类型全类名。
<select id="selectAllUsers" resultType="com.baizhi.entity.User">
select user_id as userId,user_name as username,password
from t_user
</select>
4.2 返回值类型为void
方法返回值类型为void,resultType属性不需要添加。
<delete id="deleteUserById">
delete from t_user
where user_id = #{id}
</delete>
注意:MyBatis默认不提交事务,需要手动提交事务!!!
@Test
public void testDeleteUserById() throws IOException{
//1 读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2 创建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3 创建SqlSession
SqlSession sqlSession = factory.openSession();
//4 获取Dao实现类对象
UserDao dao = sqlSession.getMapper(UserDao.class);
//5 调用dao方法
dao.deleteUserById(2);
sqlSession.commit();//必须要手动提交事务
//6 关闭sqlSession
sqlSession.close();
}
5 MyBatis的数据绑定
数据绑定:将方法形参接收的数据绑定到sql语句中。
5.1 一个参数
方法:
public User selectUserById(Integer id);
mapper.xml
<select id="selectUserById" resultType="com.baizhi.entity.User">
select user_id as userId,user_name as username,password from t_user
where user_id = #{a}
</select>
一个参数时,#{}中内容可以任意,实战时#{}中保持和参数名相同。
5.2 多个参数
方法:
public User selectUserByNameAndPassword(@Param("username")String name,@Param("password")String password);
mapper.xml
<select id="selectUserByNameAndPassword" resultType="com.baizhi.entity.User">
select user_id as userId,user_name as username,password from t_user
where user_name = #{username} and password = #{password}
</select>
多个参数时,使用Param注解给参数起别名,在mapper.xml中#{}里填注解值。
注意:一个参数时,也可以使用Param注解,但是一旦使用注解,#{}中必须使用注解值。
5.3 对象参数
不使用Param注解时:#{}中直接使用属性名
-
方法:
public void updateUser(User u);
-
mapper.xml
<update id="updateUser"> update t_user set user_name = #{username}, password = #{password} where user_id = #{userId} </update>
使用注解时:#{}中填 注解名.属性名
-
方法
public void updateUser(@Param("user")User u);
-
mapper.xml
<update id="updateUser"> update t_user set user_name = #{user.username}, password = #{user.password} where user_id = #{user.userId} </update>
实战时:一个参数时不用注解,多个参数时使用注解。
6 MyBatisUtils工具类
MyBatisUtils:抽取MyBatis编程中共性的代码。
基本思路:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j86GEipg-1630934134613)(MyBatis day01.assets/image-20210602181341043.png)]
第1版MyBatisUtils
public class MyBatisUtils {
//创建SqlSession
public static SqlSession openSession() {
//1 读取配置文件
InputStream in = null;
try {
in = Resources.getResourceAsStream("mybatis-config.xml");
}catch(Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
//2 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3 创建SqlSession对象
SqlSession sqlSession= factory.openSession();
return sqlSession;
}
//关闭sqlSession
public static void close(SqlSession sqlSession) {
sqlSession.close();
}
}
优化的思路:
-
Resources:读取配置文件(IO读取)
建议:读取配置文件只发生一次,定义在静态代码块中
-
SqlSessionFactory:创建SqlSession对象
建议:重量级对象(占据更多的内存),应该保证其单例
-
SqlSession:封装了一个Connection
建议:保证service和dao获取到同1个sqlSession
MyBatisUtils最终版本
public class MyBatisUtils {
//2 创建SqlSessionFactory对象
private static SqlSessionFactory factory;
static {
//1 读取配置文件
InputStream in = null;
try {
in = Resources.getResourceAsStream("mybatis-config.xml");
factory = new SqlSessionFactoryBuilder().build(in);
}catch(Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
//创建SqlSession
public static SqlSession openSession() {
//3 创建SqlSession对象
SqlSession sqlSession= factory.openSession();
return sqlSession;
}
//关闭sqlSession
public static void close(SqlSession sqlSession) {
sqlSession.close();
}
}
7 mybatis-config.xml中的标签
7.1 typeAlias
给实体类型起别名:
- 为单个实体类起别名
<typeAliases>
<!--
typeAlias 作用:用来给实体类型取短别名
type: 实体类型全类名
alias: 短别名
注意事项:1 定义了短别名后,依然可以使用全类名
2 短别名使用时不区分大小写
3 mapper的namespace属性绝对不能使用短别名,实战时也就不会为dao配置短别名
-->
<typeAlias type="com.baizhi.entity.User" alias="User"/>
</typeAliases>
- 批量起别名
<typeAliases>
<!--
package: 为指定包下所有实体类批量的注册短别名,短别名默认是类名
示例: com.baizhi.entity.User ==> User
name:设置entity包路径 -->
<package name="com.baizhi.entity"/>
</typeAliases>
推荐:使用package批量起别名
注意:
-
定义了短别名后,依然可以使用全类名
-
无论哪种形式起别名,在使用时别名不区分大小写
-
mapper标签的namespace属性不能使用别名,实战时也就不会为dao配置短别名
-
使用批量注册短别名的方式时,可以使用Alias注解自定义短别名
@Alias("u") public class User implements Serializable { private Integer userId; private String username; private String password; ... }
7.2 properties
配置文件参数化:将数据库相关的参数抽取到小配置文件中,在config.xml里获取小配置文件的参数,方便运维人员修改配置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yh5oMzuK-1630934134614)(MyBatis day01.assets/image-20210602213800416.png)]
-
将数据库参数抽取到小配置文件中(jdbc.properties)
driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/baizhi?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai username=root password=123456
-
config.xml中读取jdbc.properties
<!--resource:小配置文件的路径--> <properties resource="jdbc.properties"></properties>
-
config.xml中使用参数
<configuration> <properties resource="jdbc.properties"></properties> <typeAliases> <!-- <typeAlias type="com.baizhi.entity.User" alias="User"/> --> <!-- 默认给指定包下以及子包下所有的类起别名(短类名) --> <package name="com.baizhi.entity"/> </typeAliases> <!-- 配置数据库环境 environments下可以配置多个environment(数据库环境) --> <environments default="dev"> <environment id="dev"> <!-- 配置事务的管理方式: JDBC:必须手动管理 MANAGED:委托给第3方有事务管理能力的框架或者容器,比如Spring框架 --> <transactionManager type="JDBC"></transactionManager> <!-- 连接池: type: POOLED 使用连接池 UNPOOLED 不使用连接池 --> <dataSource type="POOLED"> <property name="driver" value="${driverClassName}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!-- 配置mapper.xml的路径 --> <mappers> <mapper resource="com/baizhi/dao/UserDaoMapper.xml"/> </mappers> </configuration>
7.3 mappers
自动扫描dao包下的mapper.xml配置文件,达到批量注册mapper.xml的效果。
<mappers>
<!--
package: 批量注册mapper.xml
name:要扫描的dao包名
要求:mapper.xml要和dao接口同名且同包
-->
<package name="com.baizhi.dao"/>
</mappers>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MMEKmH6c-1630934134614)(MyBatis day01.assets/image-20210602213417922.png)]
MyBatis官方建议 dao改名叫mapper,XxxDao改名为XxxMapper!!!
8 Servlet整合MyBatis
8.1 整合思路
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n8JL436C-1630934134615)(MyBatis day01.assets/image-20210604222133693.png)]
Dao实现方式的改变影响的只有Service层的实现类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4SaHVvQJ-1630934134616)(MyBatis day01.assets/image-20210604222232104.png)]
Service的变化主要有2点:
- 获取Dao对象的方式发生变化
- 事务控制的方式发生变化
8.2 总结开发步骤
-
搭建开发环境
-
新建一个web项目
-
导入jar包
<!-- 声明依赖 --> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- 引入数据库驱动依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <!-- hutool工具类 --> <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.3.10</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <!-- Servlet-api 编译servlet需要 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --> <!-- jsp-api 运行jsp需要 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl --> <!-- https://mvnrepository.com/artifact/jstl/jstl --> <!-- jstl 和 taglibs 是jsp引入标签库需要的依赖 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/taglibs/standard --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- 引入mybatis依赖 --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.30</version> </dependency> </dependencies>
-
导入配置文件
-
log4j.properties 必须在main/resources
-
jdbc.properties 在main/resources (规范)
-
springmvc-servlet.xml 必须在main/resources
-
xxxMapper.xml 在main/resources/com/baizhi/dao(mapper)
-
mybatis-config.xml 在main/resources(规范)
-
-
配置文件初始化(mybatis-config.xml)
<configuration> <properties resource="jdbc.properties"></properties> <typeAliases> <!-- <typeAlias type="com.baizhi.entity.User" alias="User"/> --> <!-- 默认给指定包下以及子包下所有的类起别名(短类名) --> <package name="com.baizhi.entity"/> </typeAliases> <!-- 配置数据库环境 environments下可以配置多个environment(数据库环境) --> <environments default="dev"> <environment id="dev"> <!-- 配置事务的管理方式: JDBC:必须手动管理 MANAGED:委托给第3方有事务管理能力的框架或者容器 --> <transactionManager type="JDBC"></transactionManager> <!-- 连接池: type: POOLED 使用连接池 UNPOOLED 不使用连接池 --> <dataSource type="POOLED"> <property name="driver" value="${driverClassName}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!-- 配置mapper.xml的路径 --> <mappers> <!-- <mapper resource="com/baizhi/dao/UserDaoMapper.xml"/> --> <package name="com.baizhi.dao"/> </mappers> </configuration>
注意:mybatis-config.xml要根据具体项目进行微调
同时一定解决Maven项目的2个问题:
- 新建webapp以及WEB-INF及其子内容解决
- 通过properties标签修改项目编解码集和JDK版本
-
-
建表
-
实体类
-
dao
- 接口:和之前一样
- 实现:mapper.xml
-
service
- 接口:和之前一样
- 实现: 修改2点
- 事务控制方式
- dao获取方式
-
test 在test/java
-
Controller+jsp
-
集成测试
重点:
- 数据绑定方式
- resultMap
- MyBatisUtils(使用层面)
- Servlet整合MyBatis开发步骤
name=“url” value="
u
r
l
"
/
>
<
p
r
o
p
e
r
t
y
n
a
m
e
=
"
u
s
e
r
n
a
m
e
"
v
a
l
u
e
=
"
{url}"/> <property name="username" value="
url"/><propertyname="username"value="{username}"/>
<!-- 配置mapper.xml的路径 -->
<mappers>
<!-- <mapper resource="com/baizhi/dao/UserDaoMapper.xml"/> -->
<package name="com.baizhi.dao"/>
</mappers>
</configuration>
```
注意:mybatis-config.xml要根据具体项目进行微调
同时一定解决Maven项目的2个问题:
- 新建webapp以及WEB-INF及其子内容解决
- 通过properties标签修改项目编解码集和JDK版本
-
建表
-
实体类
-
dao
- 接口:和之前一样
- 实现:mapper.xml
-
service
- 接口:和之前一样
- 实现: 修改2点
- 事务控制方式
- dao获取方式
-
test 在test/java
-
Controller+jsp
-
集成测试
重点:
- 数据绑定方式
- resultMap
- MyBatisUtils(使用层面)
- Servlet整合MyBatis开发步骤