Mybatis框架学习(1)--框架搭建以及CRUD操作
一、什么是MyBatis

- MyBatis 是一款优秀的持久层框架;
-
MyBatis 避免了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作;
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录;
- MyBatis原本是apache的一个开源项目ibatis,2010年该项目由apache迁移到google code,并且改名为MyBatis;
- MyBatis官方文档:https://mybatis.org/mybatis-3/zh/index.html
二、MyBatis的特点
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现;
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求;
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性;
- 提供映射标签,支持对象与数据库的ORM(对象关系映射)字段关系映射;
- 提供xml标签,支持编写动态sql
- ......
三、MyBatis快速入门
1、思路流程
环境搭建---导入Mybatis的依赖---代码编写---测试
2、代码演示
①搭建实验的数据库和表
1 CREATE DATABASE ssmbuild; 2 USE ssmbuild; 3 DROP TABLE IF EXISTS books; 4 5 CREATE TABLE books( 6 bookID INT(10) PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '书id', 7 bookName VARCHAR(100) NOT NULL COMMENT '书名', 8 bookCounts INT(10) NOT NULL COMMENT '数量', 9 detail VARCHAR(200) NOT NULL COMMENT '描述' 10 ); 11 12 INSERT INTO books(bookID,bookName,bookCounts,detail) VALUES 13 (1,'java',1,'从入门到精通'), 14 (2,'MySQL',10,'从删库到跑路'), 15 (3,'Linux',5,'从入门到进门');
②导入Mybatis的相关依赖( pom.xml 文件) -- 可以在GitHub上或者官方文档上查找
1 <dependencies> 2 <dependency> 3 <groupId>org.mybatis</groupId> 4 <artifactId>mybatis</artifactId> 5 <version>3.4.5</version> 6 </dependency> 7 8 <!--Java 连接MySQL需要驱动包,否则JDBC无法访问数据库--> 9 <dependency> 10 <groupId>mysql</groupId> 11 <artifactId>mysql-connector-java</artifactId> 12 <version>5.1.32</version> 13 </dependency> 14 </dependencies>
③编写Mybatisde的核心配置文件 -- 查看Mybatis官方文档
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <environments default="development"> 7 <environment id="development"> 8 <transactionManager type="JDBC"/> 9 <dataSource type="POOLED"> 10 <property name="driver" value="com.mysql.jdbc.Driver"/> 11 <property name="url" value="jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8"/> 12 <property name="username" value="root"/> 13 <property name="password" value="root"/> 14 </dataSource> 15 </environment> 16 </environments> 17 18 <mappers> 19 <mapper resource="mapper/BookMapper.xml"/> 20 </mappers> 21 22 </configuration>
④编写Mybatis工具类 -- 查看Mybatis官方文档
1 import org.apache.ibatis.io.Resources; 2 import org.apache.ibatis.session.SqlSession; 3 import org.apache.ibatis.session.SqlSessionFactory; 4 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 5 6 import java.io.IOException; 7 import java.io.InputStream; 8 9 public class MybatisUtils { 10 11 private static SqlSessionFactory sqlSessionFactory; 12 static{ 13 try { 14 String resource = "mybatis-config.xml"; 15 InputStream is = Resources.getResourceAsStream(resource); 16 sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 } 21 22 public static SqlSession getSession(){ 23 return sqlSessionFactory.openSession(); 24 } 25 }
⑤创建实体类以及Mapper接口
【Book实体类】
1 public class Book { 2 private Integer bookID; 3 private String bookName; 4 private Integer bookCounts; 5 private String detail; 6 7 public Book() { 8 } 9 10 public Book(Integer bookID, String bookName, Integer bookCounts, String detail) { 11 this.bookID = bookID; 12 this.bookName = bookName; 13 this.bookCounts = bookCounts; 14 this.detail = detail; 15 } 16 17 public Integer getBookID() { 18 return bookID; 19 } 20 21 public void setBookID(Integer bookID) { 22 this.bookID = bookID; 23 } 24 25 public String getBookName() { 26 return bookName; 27 } 28 29 public void setBookName(String bookName) { 30 this.bookName = bookName; 31 } 32 33 public Integer getBookCounts() { 34 return bookCounts; 35 } 36 37 public void setBookCounts(Integer bookCounts) { 38 this.bookCounts = bookCounts; 39 } 40 41 public String getDetail() { 42 return detail; 43 } 44 45 public void setDetail(String detail) { 46 this.detail = detail; 47 } 48 49 @Override 50 public String toString() { 51 return "Book{" + 52 "bookID=" + bookID + 53 ", bookName='" + bookName + '\'' + 54 ", bookCounts=" + bookCounts + 55 ", detail='" + detail + '\'' + 56 '}'; 57 } 58 }
【BookMapper接口】
1 import pojo.Book; 2 import java.util.List; 3 4 public interface BookMapper { 5 6 //查询所有的书籍信息 7 List<Book> selectBook(); 8 }
⑥编写Mapper.xml的配置文件
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="mapper.BookMapper"> 6 <select id="selectBook" resultType="pojo.Book"> 7 select * from books 8 </select> 9 </mapper>
【说明】
1、mapper.xml配置文件中的namaspace中的名称必须为对应Mapper接口或Dao接口的全限定类名,必须一致!!!
2、select标签中的id为namespace对应接口中的方法名。
⑦编写测试类
1 import org.apache.ibatis.session.SqlSession; 2 import pojo.Book; 3 import utils.MybatisUtils; 4 5 import java.util.List; 6 7 public class MyTest { 8 public static void main(String[] args) { 9 SqlSession session = MybatisUtils.getSession(); 10 BookMapper mapper = session.getMapper(BookMapper.class); 11 List<Book> books = mapper.selectBook(); 12 for (Book book : books) { 13 System.out.println(book); 14 } 15 } 16 }
⑧测试结果

3、运行过程中可能出现的问题
①Maven静态资源过滤的问题
解决方案:在pom.xml配置文件中添加如下代码块:
1 <build> 2 <resources> 3 <resource> 4 <directory>src/main/java</directory> 5 <includes> 6 <include>**/*.properties</include> 7 <include>**/*.xml</include> 8 </includes> 9 <filtering>false</filtering> 10 </resource> 11 <resource> 12 <directory>src/main/resources</directory> 13 <includes> 14 <include>**/*.properties</include> 15 <include>**/*.xml</include> 16 </includes> 17 <filtering>false</filtering> 18 </resource> 19 </resources> 20 </build>
②在核心配置文件中由于映射器Mappers未正确配置而出现错误,常见错误总结如下:



[1]使用 <mapper resource="xxxMapper.xml"/>时,包名之间使用"/",不要使用".",接口和其对应的Mapper.xml配置文件的名称可以不相同;
[2]核心配置文件中使用<package name=""></package>或<mapper class=""></mapper>时,包名之间使用".",接口和其对应的Mapper.xml配置文件必须同包同名。
[tips]
为了避免因为映射器配置错误而出现Exception in thread "main" org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)、org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource mapper.BookDao.xml等异常(xxx.xml包名之间一定使用“/"),我们搭建环境的过程中,接口和其对应的配置文件最好同包同名。
四、Mybatis实现CRUD操作
1、查询操作--select
- select标签时Mybatis中最常用的标签之一,该标签有很多属性可以配置,常见的属性有:
- id:对应接口中的方法名
- parameterType:传入SQL语句的参数类型,在该参数中可以使用万能的Map实现参数的传递,百试不爽^_^
- resultType:SQL语句返回返回值的类型
- 【需求:根据id查询Book】
①在BookMapper中添加对应的方法
1 public Books findBookByID(int id); //根据id查询Book
②在BookMapper.xml配置文件中添加select语句
1 <select id="findBookByID" resultType="com.yif.pojo.Books" parameterType="int"> 2 select * from books where bookID = #{id} 3 </select>
③测试类中的测试
1 public static void main(String[] args) { 2 SqlSession sqlSession = MybatisUtils.getSqlSession(); 3 BookDao bookDao = sqlSession.getMapper(BookDao.class); 4 Books book = bookDao.findBookByID(1); 5 System.out.println(book); 6 sqlSession.close(); 7 }

【说明】
在进行参数传递时,如果我们的实体类或者待查询数据库中表的字段过多时,我们可以考虑使用"万能的Map",使用规则如下:
1、使用Map传递参数,直接在sql语句中取出map中的key即可,实例如下图所示:

2、增加操作--insert
①在BookMapper中添加对应的方法
1 public int addBook(Books book);
②在BookMapper.xml配置文件中添加insert语句
1 <insert id="addBook" parameterType="com.yif.pojo.Books"> 2 insert into books values (#{bookID},#{bookName},#{bookCounts},#{detail}) 3 </insert>
③测试类中的测试
1 public static void main(String[] args) { 2 SqlSession sqlSession = MybatisUtils.getSqlSession(); 3 BookDao bookDao = sqlSession.getMapper(BookDao.class); 4 bookDao.addBook(new Books(4,"python",10,"入门基础")); 5 sqlSession.commit(); //手动提交事务,否则增加的内容提交不到数据库中 6 sqlSession.close(); 7 }
【注意】由于增、删、改操作会修改数据库中的内容,在执行这些操作时,需要提交事务!!!
3、修改Book的信息--update
4、根据id删除表中的某一Book -- delete
5、小结
①所有的增删改操作都需要提交事务;
②接口中所有的普通参数,尽量采用方法名(@Param("newpara")int para),在sql中通过#{newpara}来获取传递的参数;
③根据业务的需求,可以考虑使用Map来实现参数的传递。
五、Mybatis配置解析
1.核心配置文件
- Mybatis的核心配置文件一般命名为:mybatis-config.xml;
- MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息;
- 可配置的内容如下
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
注意元素节点的顺序,如果顺序不对,会报错!!!
蓝色标注出的配置为常见的配置内容,必须熟悉!!!
2、环境配置--environments
1 <environments default="development"> 2 <environment id="development"> 3 <transactionManager type="JDBC"/> 4 <dataSource type="POOLED"> 5 <property name="driver" value="com.mysql.jdbc.Driver"/> 6 <property name="url" value="jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8"/> 7 <property name="username" value="root"/> 8 <property name="password" value="root"/> 9 </dataSource> 10 </environment> 11 </environments>
【说明】
①Mybatis可以配置多个environment,但是在每个SqlSessionFactory实例中只能选择一种环境;例如在上述的配置文件中,除了"development“环境外,还可以配置"test"环境;
②Mybatis默认的事务管理器是JDBC,连接池的类型为POOLED
③关于事务管理器和连接池的类型详情参考Mybatis官方文档。
3、属性--properties
- 我们可以通过properties属性实现对外配配置文件的引用;
- 数据库环境配置中的这些属性可以在外部进行配置并并且进行动态替换,既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置;
我们可以通过使用properties来优化我们的配置文件:
step1:在resources目录下新建一个db.properties的文件
1 driver=com.mysql.jdbc.Driver 2 url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8 3 username=root 4 password=root
step2:将db.properties文件导入到propertiespe配置中
1 <properties resource="db.properties"> 2 <property name="password" value="123456"></property> 3 </properties> 4 5 <environments default="development"> 6 <!--环境配置: 7 可以配置多个环境,但是在实际开发中只可以指定其中的一个 8 通过切换environments标签中的default属性的取值,来选择不同的环境 9 --> 10 <environment id="development"> 11 <transactionManager type="JDBC"/> 12 <dataSource type="POOLED"> 13 <property name="driver" value="${driver}"/> 14 <property name="url" value="${url}"/> 15 <property name="username" value="${username}"/> 16 <property name="password" value="${password}"/> 17 </dataSource> 18 </environment> 19 20 <environment id="test"> 21 <transactionManager type="MANAGED"></transactionManager> 22 <dataSource type="UNPOOLED"> 23 <property name="driver" value="${driver}"/> 24 <property name="url" value="${url}"/> 25 <property name="username" value="${username}"/> 26 <property name="password" value="${password}"/> 27 </dataSource> 28 </environment> 29 30 </environments> 31 32 <mappers> 33 <mapper resource="com/yif/mapper/BookMapper.xml"></mapper> 34 <!--<package name="com.yif.mapper"></package>--> 35 <!--<mapper class="com.yif.mapper.BookMapper"></mapper>--> 36 </mappers>
【关于properties的说明】
①可以直接引入外部配置文件;
②可以在properties中添加一些属性配置;
③如果properties中的属性配置与外部配置文件中属性配置不一致时,优先使用外部配置文件的!
4、类型别名--typeAliases(含两种方式)
- 类型别名可为 Java 类型设置一个缩写名字;
- 使用类型别名的目的在于降低冗余的全限定类名书写
1 <!-- 2 给实体类起别名 3 方式一:使用typeAlias标签给单个实体类取别名 4 方式二:使用package标签给某一个包下的所有实体类起别名,别名默认为类名小写 5 --> 6 <typeAliases> 7 <typeAlias type="com.yif.pojo.Books" alias="Books"></typeAlias> 8 </typeAliases>
5、映射器--mappers
- 定义映射SQL语句的配置文件;
- 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括
file:///形式的 URL),或类名和包名等; - 映射器是Mybatis中最核心的组件之一。
1 <!-- 使用相对于类路径的资源引用 --> 2 <mappers> 3 <mapper resource="com/yif/mapper/BookMapper.xml"></mapper>4 </mappers>
1 <!-- 使用映射器接口实现类的完全限定类名 --> 2 <mappers> 3 <mapper class="com.yif.mapper.BookMapper"></mapper> 4 </mappers>
1 <!-- 将包内的映射器接口实现全部注册为映射器 --> 2 <mappers> 3 <package name="com.yif.mapper"></mapper> 4 </mappers>
这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件了。
6、其他配置预览
- settings --详情查看Mybatis官方文档
- 缓存开启关闭--cacheEnabled
- 日志实现--logImpl
- 1、LOG4J及其使用步骤
- step1、在pom.xml中导入log4j的依赖
- 1、LOG4J及其使用步骤
1 <dependency> 2 <groupId>log4j</groupId> 3 <artifactId>log4j</artifactId> 4 <version>1.2.17</version> 5 </dependency>
-
-
-
- step2、编写log4j的配置文档log4j.properties
-
-
1 #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码 2 log4j.rootLogger=DEBUG,console,file 3 4 #控制台输出的相关设置 5 log4j.appender.console = org.apache.log4j.ConsoleAppender 6 log4j.appender.console.Target = System.out 7 log4j.appender.console.Threshold=DEBUG 8 log4j.appender.console.layout = org.apache.log4j.PatternLayout 9 log4j.appender.console.layout.ConversionPattern=[%c]-%m%n 10 11 #文件输出的相关设置 12 log4j.appender.file = org.apache.log4j.RollingFileAppender 13 #日志文件的位置 14 log4j.appender.file.File=./log/yif.log 15 log4j.appender.file.MaxFileSize=10mb 16 log4j.appender.file.Threshold=DEBUG 17 log4j.appender.file.layout=org.apache.log4j.PatternLayout 18 log4j.appender.file.layout.ConversionPattern=[%p][%d{yyyy-MM-dd}][%c]%m%n 19 20 #日志输出级别 21 log4j.logger.org.mybatis=DEBUG 22 log4j.logger.java.sql=DEBUG 23 log4j.logger.java.sql.Statement=DEBUG 24 log4j.logger.java.sql.ResultSet=DEBUG 25 log4j.logger.java.sql.PreparedStatement=DEBUG
-
-
-
- step3、获取Logger对象
-
-
1 public class MyTest { 2 3 static Logger logger = Logger.getLogger(MyTest.class); 4 5 @Test 6 public void test(){ 7 logger.info("infor:进入test方法"); 8 SqlSession sqlSession = MybatisUtils.getSqlSession(); 9 BookMapper mapper = sqlSession.getMapper(BookMapper.class); 10 Books book = mapper.findBookByID(1); 11 System.out.println(book); 12 } 13 }
-
-
- 2、STDOUT_LOGGING
- 是否开启驼峰命名自动映射--mapUnderscoreToCamelCase
- 若开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
-
六、作用域和生命周期
1、Mybatis的执行流程

①SqlSessionFactoryBuilder的作用在于创建SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder就失去了作用,所以它只能存在于创建SqlSessionFactory的方法中,而不能让其长期存在。故SqlSessionFactoryBuilder实例的最佳作用域是方法作用域(也就是局部方法变量);
②SqlSessionFactory其作用是创建SqlSession接口对象。由于Mybatis的本质就是java对数据库的操作(SqlSessionFactory可以被认为是一个数据库的连接池),所以SqlSessionFactory的生命周期存在于整个Mybatis的应用之中,即一旦创建SqlSessionFactory,就需要长期保存,直至不再使用Mybatis应用。因此可以认为SqlSessionFactory的生命周期等同于Mybatis的应用周期;
③由于SqlSessionFactory可以被认为是一个数据库的连接池,它占据着数据库的连接资源。如果创建多个SqlSessionFactory,那么就存在多个数据库连接池对象,这样不利于对数据库资源的控制,因此在一般的应用中,我们希望SqlSessionFactory作为一个单例,让其在应用中被共享,所以说SqlSessionFactory的最佳作用域是应用作用域;
④如果说sqlSessionFactory相当于数据库操作中的连接池,那么SqlSession就相当于一个数据库连接(Connection对象),所以它应该存活在一个业务请求中:在处理完整个请求后,应该关闭这条连接,将其归还到sqlSessionFactory,否则数据库资源就很快被耗费完。因此SqlSession的最佳作用域是请求或方法作用域。
(未完待续......)
浙公网安备 33010602011771号