Mybatis
1、简介
1.1什么是 MyBatis?
- MyBatis 是一款优秀的持久层框架,
- 它支持自定义 SQL、存储过程以及高级映射。
- MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
如何获得Mybatis?
-
中文文档:MyBatis中文网
-
Maven仓库:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency>
1.2持久化
数据持久化
- 持久化就是就将程序的数据在持久状态和瞬时状态转化的过程
- 内存:断电即失
- 数据库:IO文件持久化
为什么要持久化?
- 有一些对象不能让它丢掉
- 内存太贵
1.3持久层
Dao层、Service层,Controller层
- 完成持久化工作的代码块
- 层界线十分明显
1.4为什么需要Mybatis
- 方便
- 传统的JDBC代码太复杂,需要简化
- 帮助程序员将数据存入到数据库中
- 不用Mybatis也可以,技术没有高低之分
2、第一个Mybatis程序
思路:搭建环境–>导入Mybatis–>编写代码–>测试
2.1搭建环境
新建项目
-
新建一个Maven项目
-
删除src目录
-
导入Maven依赖
<!--导入依赖--> <dependencies> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> </dependencies>
2.2 创建一个模块
-
编写Mybatis的核心配置文件:resources文件夹下创建
<?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="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> </configuration>
-
编写Mybatis的工具类:创建utils文件夹,并创建MybatisUtils文件
public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
2.3编写代码
- 实体类代码
public class User {
private int id;
private String name;
private String password;
}
再构建get和set方法
-
Dao接口
public interface UserDao { // 查询所有 List<User> getUserList(); }
-
接口实现类:在resource创建mapper文件夹,并创建UserMapper.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:绑定一个对应的Dao/Mapper接口,名字需要和接口的包名一致--> <mapper namespace="com.zzs.dao.UserDao"> <!--select查询语句--> <select id="getUserList" resultType="com.zzs.pojo.User"> select * from user </select> <mapper>
-
测试
@Test public void test(){ // 第一步:获得sqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); // 第二步:获得getMapper UserDao mapper = sqlSession.getMapper(UserDao.class); List<User> userList = mapper.getUserList(); for (User user : userList) { System.out.println(user); } //关闭流 sqlSession.close(); }
3.CRUD操作
1.namespace
<!--namespace:绑定一个对应的Dao/Mapper接口,名字需要和接口的包名一致-->
<mapper namespace="com.zzs.dao.UserDao">
</mapper>
2.CRUD
在Dao层定义方法
public interface UserDao {
// 查询所有
List<User> getUserList();
// 添加
int add(User user);
// 删除
int delete(int id);
// 修改
int update(User user);
}
在映射中写SQL语句
<mapper namespace="com.zzs.dao.UserDao">
<!--select查询语句-->
<select id="getUserList" resultType="com.zzs.pojo.User">
select * from user
</select>
<!--insert添加语句-->
<insert id="add" parameterType="com.zzs.pojo.User">
insert into user values (#{id},#{name},#{password})
</insert>
<!--delete删除语句-->
<delete id="delete" parameterType="com.zzs.pojo.User">
delete from user where id=#{id}
</delete>
<!--update修改语句-->
<update id="update" parameterType="com.zzs.pojo.User">
update user set name=#{name},password=#{password} where id=#{id}
</update>
</mapper>
测试
public class UserDaoTest {
@Test
public void test(){
// 第一步:获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 第二步:获得getMapper
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
@Test
public void testAdd(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int row = mapper.add(new User(4, "张宇", "123456"));
if (row==0){
System.out.println("插入成功");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void testDelete(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int row = mapper.delete(5);
if (row!=0){
System.out.println("删除成功");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void testUpdate(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int row = mapper.update(new User(3,"张宇","777777"));
if (row!=0){
System.out.println("修改成功");
}
sqlSession.commit();
sqlSession.close();
}
}
3.万能Map
假设,我们在实体类中或者数据库中的表、字段或者参数过多时,我们应当考虑使用Map!可以自己定义参数,不需要与实体类和数据库中定义的名相同,参数的数量也可以自己设置。
// 万能的Map
int addUser(Map<String,Object> map);
<!--对象中的属性,可以直接取出来 传递map的key-->
<insert id="addUser" parameterType="map">
insert into user (id,name,password) values (#{userid},#{userName},#{pwd})
</insert>
@Test
public void addUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
Map<String, Object> map = new HashMap<>();
map.put("userid",9);
map.put("userName","蔡文姬");
map.put("pwd","000000");
mapper.addUser(map);
sqlSession.close();
}
Map传递参数,直接在SQL中取出key即可!【parameterType=“map”】
对象传递参数,直接在SQL中取出对象的属性即可!【parameterType=“object”】
只用一个基本类型参数的情况下,可以直接在SQL中取到!
多个参数用Map,或者注释!
4.思考题
模糊查询怎么写?
1、java代码执行的时候,传递通配符% %
select * from user where name like #{value}
List<User> userList = mapper.getUserLike("%张%");
2、在SQL中拼接使用通配符
select * from user where name like "%"#{value}"%"
List<User> userList = mapper.getUserLike("张");
// 模糊查询
List<User> getUserLike(String value);
<select id="getUserLike" resultType="com.zzs.pojo.User">
select * from user where name like #{value}
</select>
@Test
public void getUserLike(){
// 第一步:获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 第二步:获得getMapper
UserDao mapper = sqlSession.getMapper(UserDao.class);
/*List<User> userList = mapper.getUserLike("张");*/
List<User> userList = mapper.getUserLike("%张%");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
3、在SQL中使用concat拼接
<select id="getUserLike" resultType="com.zzs.pojo.User">
select * from user where name like concat('%',#{value},'%')
</select>
4、使用${}
<select id="getUserLike" resultType="com.zzs.pojo.User">
select * from user where name like '%${value}%'
</select>
4、配置解析
1.核心配置文件
-
mybatis-config.xml
-
Mybatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息
configuration(配置) properties(属性) settings(设置) typeAliases(类型别名) typeHandlers(类型处理器) objectFactory(对象工厂) plugins(插件) environments(环境配置) environment(环境变量) transactionManager(事务管理器) dataSource(数据源) databaseIdProvider(数据库厂商标识) mappers(映射器)
2.配置环境(environment)
Mybatis可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个SQLSessionFactory实例只能选择一种环境
Mybatis默认的事务管理器是JDBC,连接池:POOLED
学会
3、属性(properties)
我们可以通过properties属性来实现引用配置文件
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。【db.properties】
编写一个配置文件
db.properties
driver="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"
username="root"
password="123456"
在核心文件中引入:
<properties resource="db.properties">
<property name="" value=""/>
</properties>
- 可以引入外部文件
- 可以在其中增加一些属性配置
- 如果两个文件有相同的字段,优先使用外部文件
4.类型别名(typeAliases)
-
类型别名可为 Java 类型设置一个缩写名字。
-
它仅用于 XML 配置,意在降低冗余的全限定类名书写
<!--添加别名--> <typeAliases> <typeAlias type="com.zzs.pojo.User" alias="User"/> </typeAliases>
也可以指定一个包名,Mybatis会在包名下面搜索需要的java Bean,比如:扫描实体类的包,它的默认别名就是这个类的类名,首字母小写
<!--添加别名-->
<typeAliases>
<package name="com.zzs.pojo" />
</typeAliases>
在实体类比较少的时候,使用第一种。
如果实体类很多,建议使用第二种。
第一种可以DIY别名,第二种不行,如果非要改,则需要在实体类上添加注解。
5.解决属性名和字段名不一致的问题
1.问题
public class User {
private int id;
private String name;
private String pwd;
}
<select id="getUserById" resultType="com.zzs.pojo.User">
select * from user where id = #{id}
</select>
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = mapper.getUserById(1);
System.out.println(user);
sqlSession.close();
}
2.解决方法
-
取别名
<select id="getUserById" resultType="com.zzs.pojo.User"> select id,name,password pwd from user where id = #{id} </select>
-
resultMap结果集映射
<!--根据ID查找--> <!--resultMap结果集映射--> <resultMap id="UserMap" type="User"> <result column="id" property="id"/> <result column="name" property="name"/> <result column="password" property="pwd"/> </resultMap> <select id="getUserById" resultMap="UserMap"> select * from user where id = #{id} </select>
可以只映射不一样的,相同的名字的可以省略不进行映射。
6.日志
log4j:
1.先导入log4j包
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2.在配置log4j
在recourse创建log4j.properties,添加如下代码:
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
7、分页
为什么要使用分页?
- 减少数据的处理量
使用Limit分页
语法:select * from user limit startIndex,pageSize
select * from user limit 1,2; 下标从第2个开始查询2条数据
select * from user limit 0,3; 下标从第0个开始,到3结束,查询三条
select * from user limit 3; 下标从0开始,到3结束
使用Mybatis实现分页,核心SQL
1.接口
// 分页
List<User> getUserLimit(Map<String,Integer> map);
2.Mapper.xml
<!--分页-->
<select id="getUserLimit" resultMap="UserMap">
select * from user limit #{startIndex},#{pageSize}
</select>
3.测试
@Test
public void getUserLimit(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
HashMap<String, Integer> map = new HashMap<String,Integer>();
map.put("startIndex",1);
map.put("pageSize",3);
List<User> users=mapper.getUserLimit(map);
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}