一、Mybatis简介
1️⃣什么是Mybatis
MyBatis 本是apache的一个开源项目【iBatis】;2010年这个项目由apache software foundation(Apache软件基金会) 迁移到了google code(谷歌的代码托管平台),并且改名为MyBatis;2013年11月迁移到Github。
MyBatis是一款优秀的持久层框架
MyBatis支持定制SQL、存储过程以及高级映射
Mybatis避免了几乎所有的JDBC代码和手动设置参数,以及获取结果集
Mybatis可以使用简单的XML或注解来配置和映射原生类型、接口和Java的POJO(Plain Old Java Objects,普通老式Java对象)为数据库中的记录
Mybatis的Maven仓库下载地址: https://mvnrepository.com/artifact/org.mybatis/mybatis
Mybatis的GitHub地址: https://github.com/mybatis/mybatis-3/releases
Mybatis的中文文档地址: https://mybatis.org/mybatis-3/zh/index.html
2️⃣持久化
持久化是将程序数据在持久状态和瞬时状态间转换的机制。通俗的讲,就是瞬时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)。
程序产生的数据首先都是在内存。
内存是不可靠的,他丫的一断电数据就没了。
那可靠的存储地方是哪里?硬盘、U盘、光盘等。
我们的程序在运行时说的持久化通常就是指将内存的数据存在硬盘。
3️⃣持久层
对于分层的概念我们知道:
业务是需要操作数据的
数据是在磁盘上的
具体业务调用具体的数据库操作,耦合度太高,复用性太差
将操作数据库的代码统一抽离出来,自然就形成了介于业务层和数据库中间的独立的层
持久层的工作:
完成持久化工作的代码块
层之间的界限非常明显
4️⃣聊聊ORM
ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法。
jpa(Java Persistence API)是java持久化规范,是orm框架的标准,主流orm框架都实现了这个标准。
hibernate: 全自动的框架,强大、复杂、笨重、学习成本较高,不够灵活,实现了jpa规范。Java Persistence API(Java 持久层 API)
MyBatis: 半自动的框架(懂数据库的人 才能操作) 必须要自己写sql,不是依照的jpa规范实现的。
很多人青睐 MyBatis ,原因是其提供了便利的 SQL 操作,自由度高,封装性好…… JPA对复杂 SQL 的支持不好,没有实体关联的两个表要做 join 的确要花不少功夫。
5️⃣MyBatis的优点和缺点
sql语句与代码分离,存放于xml配置文件中:
优点:便于维护管理,不用在java代码中找这些语句;
缺点:JDBC方式可以用打断点的方式调试,但是MyBatis调试比较复杂,一般要通过log4j日志输出日志信息帮助调试,然后在配置文件中修改。
用逻辑标签控制动态SQL的拼接:
优点:用标签代替编写逻辑代码;
缺点:拼接复杂SQL语句时,没有代码灵活,拼写比较复杂。不要使用变通的手段来应对这种复杂的语句。
查询的结果集与java对象自动映射:
优点:保证名称相同,配置好映射关系即可自动映射或者,不配置映射关系,通过配置列名=字段名也可完成自动映射。
缺点:对开发人员所写的SQL依赖很强。
编写原生SQL:
优点:接近JDBC,比较灵活。
缺点:对SQL语句依赖程度很高;并且属于半自动,数据库移植比较麻烦,比如MySQL数据库编程Oracle数据库,部分的SQL语句需要调整。
最重要的一点,使用的人多!公司需要!
二、第一个MyBatis程序
实现步骤:搭建环境—>导入MyBatis—>编写相关代码—>测试
1️⃣搭建环境
🍀(1)搭建数据库
-- 创建数据库 create database `mybatis`; use mybatis; -- 创建表 create table `user`( `id` int(20) not null, `name` varchar(30) default null, `pwd` varchar(30) default null, primary key(`id`) )engine=InnoDB default charset=utf8mb4; -- 插入数据 insert into `user`(`id`,`name`,`pwd`) values (1,'张三','123'), (2,'李四','123'), (3,'王五','123');
🍀(2)新建一个普通maven项目作为父项目,并导入sql驱动,mybatis,junit组件
<!--导入依赖--> <dependencies> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <!--Mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
🍀(3)新建一个新组件作为子级项目,普通maven的module
🍀(4)添加配置文件
- 在src->main->resources目录下新建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 default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> //数据库驱动,不同驱动可连接不同数据库服务器 <property name="url" value="${url}"/> //连接数据库的目录 <property name="username" value="${username}"/> //数据库名字,默认root <property name="password" value="${password}"/> //数据库密码,自己的数据库密码,一般为root </dataSource> </environment> </environments> </configuration>
2️⃣编写mybatis工具类
MybatisUtils.java:
//SqlSessionFactory --生产--> SqlSession 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(); } } //获取sqlSession //SqlSession完全包含了面向对象数据库执行SQL命令所需的方法 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession();} }
3️⃣编写相关代码
🍀(1)实体类
public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
🍀(2)Dao接口
public interface UserDao { List<User> getUserList(); }
🍀(3)xxxMapper.xml配置文件
接口的实现类要改为以xxxMapper.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/Dao接口--> <mapper namespace="com.wang.dao.UserDao"> <!--id:接口的方法,resultType:接口的返回值类型--> <select id="getUserList" resultType="com.wang.pojo.User"> select * from mybatis.user where id = #{id} </select> </mapper>
每一个Mapper.xml文件都需要在src->main->resources目录下的mybatis-config.xml核心配置文件中注册:
<mappers> <mapper resource="com/wang/dao/UserMapper.xml"> </mappers>
4️⃣测试
public class UserDaoTest { @Test public void test(){ //获取SqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //获取mapper UserDao mapper = sqlSession.getMapper(UserDao.class); List<User> list = mapper.getUserList(); for (User u:list){ System.out.println(u); } //不推荐使用以下方式 /* 这种方式能够正常工作,对使用旧版本 MyBatis 的用户来说也比较熟悉。但现在有了一种更简洁的方 式——使用和指定语句的参数和返回值相匹配的接口(比如 BlogMapper.class),现在你的代码不仅更清晰,更加 类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。 */ // List<User> list = sqlSession.selectList("com.qian.dao.UserDao.getUserList"); // for (User user : list) { // System.out.println(user); // } //关闭SqlSession sqlSession.close(); } }
三、使用Mybatis实现CRUD
1️⃣Mapper接口
public interface UserMapper { //查询全部用户 List<User> getUserList(); //根据id查询用户 User getUserById(int id); //增加新的用户 boolean insertNewUser(User u); //删除用户 boolean deleteUserById(int id); boolean deleteUserByName(String name); //修改用户 boolean updateUserById(User u); }
2️⃣xxxMapper.xml文件
<?xml version="1.0" encoding="utf8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace:命名空间,绑定mapper/Dao接口--> <!--id:接口的方法,resultType:接口的返回值类型--> <mapper namespace="com.wang.dao.UserMapper"> <select id="getUserList" resultType="com.wang.pojo.User"> select * from mybatis.user </select> <select id="getUserById" parameterType="int" resultType="com.wang.pojo.User"> select * from mybatis.user where id=#{id} </select> <!-- 对象中的属性,可以直接取出来用 --> <insert id="insertNewUser" parameterType="com.wang.pojo.User"> insert into mybatis.user (id, name, pwd) VALUES (#{id},#{name},#{pwd}) </insert> <delete id="deleteUserById" parameterType="int"> delete from mybatis.user where id=#{id} </delete> <delete id="deleteUserByName" parameterType="String"> delete from mybatis.user where name=#{name} </delete> <update id="updateUserById" parameterType="com.wang.pojo.User"> update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id} </update> </mapper>
3️⃣测试类
public class UserDaoTest { @Test public void test(){ //获取SqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); try{ //获取mapper UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 查询全表 List<User> list = mapper.getUserList(); for (User u:list){ System.out.println(u); } //根据id查询 User user = mapper.getUserById(1); System.out.println(user); //插入新用户,注意:更新,插入,删除都需要提交事务 User user1 = new User(4,"李四","25615"); boolean isInserted = mapper.insertNewUser(user1); sqlSession.commit(); //代码优化 if (mapper.insertNewUser(new User(4,"李四","25615"))) sqlSession.commit(); //删除用户 if (mapper.deleteUserById(4))sqlSession.commit(); if (mapper.deleteUserByName("李四"))sqlSession.commit(); //修改用户 if (mapper.updateUserById(new User(4,"王五","6849816")))sqlSession.commit(); }finally { //关闭SqlSession sqlSession.close(); } } }
4️⃣Map的使用
map可以代替任何的实体类,所以当我们数据比较复杂时,可以适当考虑使用map来完成相关工作。
🍀(1)写方法
UserMapper.java:
User getUser(Map<String,Object> map); boolean addUser(Map<String,Object> map);
🍀(2)写sql
UserMapper.xml:
<select id="getUser" parameterType="map" resultType="com.qian.pojo.User"> select * from mybatis.user where id=#{userId} </select> <insert id="addUser" parameterType="map"> insert into mybatis.user (id, name, pwd) VALUES (#{userId},#{userName},#{password}) </insert>
🍀(3)测试
Test.java:
@Test public void test(){ //获取SqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String, Object> map = new HashMap<String, Object>(); map.put("userId",5); User user = mapper.getUser(map); System.out.println(user); map.put("userId",5); map.put("userName","孙悟空"); map.put("password","123456"); if (mapper.addUser(map)) sqlSession.commit(); sqlSession.close(); }
5️⃣模糊查询
🍀方案一:在Java代码中拼串
Test.java:
string name = "%IT%"; list<name> names = mapper.getUserByName(name);
UserMapper.xml:
<select id= "getUsersByName"> select * from user where name like #{name} </select>
🍀方案二:在配置文件中拼接1
Test.java:
string name = "IT"; list<User> users = mapper.getUserByName(name);
UserMapper.xml:
<select id= "getUsersByName"> select * from user where name like "%"#{name}"%" </select>
🍀方案三:在配置文件中拼接2
Test.java:
string name = "IT"; list<User> users = mapper.getUserByName(name);
UserMapper.xml:
<select id= "getUsersByName"> select * from user where name like "%${name}%" </select>