• 阶段六-Day03-MyBatis1


    一、框架介绍

    1. 框架的作用

    将许多项目封装起来,形成了框架

    2. 框架的优缺点

    1. 优点
    1.1 更好用

    框架都是对Java原生内容进行的封装,对于企业级项目开发来说,使用框架比使用原生Java更好用,写起来更简单。

    1.2 更强大

    框架封装过程中会内置一些常见必要逻辑或功能,所以在使用框架时很多能够不需要再次编码,框架本身就带有这些功能了。

    1.3 开发周期更短

    由于框架使用起来更加简单,必定会在一定程度上缩短程序的开发周期。很多IT公司最大的成本都是人员成本,缩短了项目的开发周期,对于企业来说利润更高。这也是企业为什么都喜欢使用框架的最主要原因之一。

    2. 缺点
    2.1 更多的学习成本

    不同的框架由不同的公司或组织开发与维护,不同公司或组织有着不同的习惯和规则,想要使用框架就需要学习框架如何使用,学习这些框架里面的要求。

    2.2 初学者更容易出错

    因为框架里面都封装了很多内容,想要使用框架就必须按照框架的规则进行使用。对于初学者如果不去记忆里面的规则,自己随意发挥,很容易出错。

    所以想要错误更少,学习框架时必须严格按照老师讲的去做,严格按照框架规则去使用。

    2.3 对于初学者,出了错误更难解决

    因为框架都是深度封装,对于开发者来说可能只写了一行代码,但这一行代码里面可能是几百或几千行代码的封装。一旦报错了,如果不知道框架原理是不太好解决的。

    所以想要更好的解决出现的问题,就必须要跟着老师学习框架的原理,同时要对每次出现的错误进行整理记忆,下次在出现这个错误的时候就可以快速解决了。

    4. Java中的常见框架

    Java项目无论是否使用框架,多采用MVC开发模型,一个项目被分为多层。一个Java框架可能只负责里面的一层。

    一个Java项目并不是使用一个框架就可能完成的,通常需要很多框架配合使用,才能实现一个完整的项目。

    常见Java框架分类(不仅仅就这些,列举一些常见的):

    (1)持久层框架:MyBatis、Hibernate、Spring Data、iBatis。

    (2)MVC框架:Spring MVC、Struts1、Struts2。

    (3)项目管理框架:Spring Framework、Spring Boot。

    (4)微服务框架:Spring Cloud。

    (5)权限管理框架:Spring Security、Shiro。

    并不是每个项目都需要把上面所有分类都使用上,不同的项目可能只会使用里面几个分类,但是只要使用了其中某个分类,只会选择其中一个。

    常见的组合:

    (1)SSM:Spring Framework + Spring MVC + MyBatis。最常见组合,属于Java程序员必须掌握的内容。

    (2)SSMP:Spring Framework + Spring MVC + MyBatis+MyBatis Plus。对SSM的增强,减少SQL的编写。

    (3)SSI:Spring Framework + Spring MVC/Struts1/Struts2 + iBatis。SSM的上代组合,目前很少出现。

    (4)SSH:Spring Framework + Struts1/Struts2 + Hibernate。和SSI属于同时代产品,只有在老项目维护时可能出现的技术栈。

    (5)Spring Boot + Spring Cloud。微服务架构项目常用组合。

    (6)Spring Boot+Mybatis+MybatisPlus。新项目最先选择,比SSM组合使用起来更加方便。

    (6)Spring Boot + Shiro/Spring Security。具有权限控制时的组合。

    (7)SSM + Shiro/Spring Security。具有权限控制时的组合。

    二、软件分层开发

    1. Java EE 三层模型 和 MVC模型

    Java EE 三层模型和MVC模型属于两种分层模型,一些同学可能认为这是同一个概念,其实并不然。

    Java EE中最经典的是三层模型。包含表示层(Presentation)、业务逻辑层(Business Logic)、持久层(Persistence)

    MVC 模型也是三层模型。包含模型层(Model)、视图层(View)、控制层(Controller)。

    Java EE 三层模型和MVC模型最主要的区别是:

    (1)Java EE三层模型中没有控制层,MVC中有控制层。

    (2)Java EE三层模型中业务模型层是单独一部分,就是service层,MVC中模型层包含:业务模型(业务逻辑层)和数据模型(实体类,持久层)。

    (3)Java EE三层模型中持久层就是dao层。MVC中虽然持久层在项目中是单独的包,但是在MVC概念中持久层属于模型层中。

    2. 目前Java中最常见的六层模型

    目前在软件开发过程中最常见的是六层模型,我们讲解的也是六层模型:

    (1)视图层。简单点说就是页面,可以是客户端页面技术,也可以是服务端页面技术。例如:HTML、JSP。

    (2)控制层。处于业务层和视图层之间,根据业务层结果,控制视图层显示。例如:Servlet。

    (3)实体层。就是实体类,负责封装数据,在各个层之间进行数据传递的载体。常见包名:pojo、domain、entity等。

    (4)业务逻辑层。专门编写业务逻辑代码。

    (5)数据持久层/数据访问层。负责编写调用数据库的代码。具体技术:JDBC、MyBatis等。

    (6)数据源层。一些持久化工具,负责存储数据的。例如:MySQL、Oracle等。

    3. ORM

    ORM(Object/Relation Mapping),中文名称:对象/关系 映射。是一种解决数据库发展和面向对象编程语言发展不匹配问题而出现的技术。

     使用JDBC技术时,手动实现ORM映射:

     ORM框架封装了对象/关系的自动映射。

    6.常见的ORM框架

    对于Java程序员来说,整个职业生涯可能听说过或可能用上的ORM框架:

    (1)MyBatis:目前使用最多的ORM框架。

    (2)Hibernate:零SQL的ORM框架,N年前使用最多的ORM框架。目前只能在一些老的项目中看到。

    (3)Spring Data JPA:目前个别公司中使用的ORM框架。是Spring Data家族中的一员。是对JPA(Java Persistence API,JDK5.0)的封装。

    (4)Spring Data JDBC:Spring Data中的二级项目,类似Spring Data JPA,但框架的功能要比Spring Data JPA少一些。

    三、MyBatis介绍

    1. 介绍

    MyBatis 是一款优秀的ORM框架,MVC分层开发中的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

    四、第一个MyBatis项目

    2. 创建Maven项目并添加依赖

    创建一个Maven项目(示例中叫做:maven1),并配置pom.xml。

    需要添加MyBatis的依赖和MySQL驱动的依赖。(文档制作时MyBatis最新版本为3.5.9,mysql驱动最新版本为8.0.29)因为MyBatis的底层也是MySQL,JDBC实现的

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <groupId>com.shgroupId>
    6. <artifactId>MyBatis01artifactId>
    7. <version>1.0-SNAPSHOTversion>
    8. <dependencies>
    9. <dependency>
    10. <groupId>org.mybatisgroupId>
    11. <artifactId>mybatisartifactId>
    12. <version>3.5.9version>
    13. dependency>
    14. <dependency>
    15. <groupId>mysqlgroupId>
    16. <artifactId>mysql-connector-javaartifactId>
    17. <version>8.0.28version>
    18. dependency>
    19. dependencies>
    20. project>

    3. 创建MyBatis全局配置文件

    在项目的src/main/resources目录下新建mybatis.cfg.xml文件。并在配置文件中填写下面内容。

    配置文件解释:

    1. XML文档头是XML文件必须有的。

    2. DOCTYPE声明文档类型,引入外部约束。

    3. 是根节点。

    4. 的default属性取值必须是下面某个标签的id属性值。表示当前MyBatis框架到底使用哪个环境。

    5. 的id值是自定义的。表示当前数据库环境的名称。在全局配置文件中标签可以有多个,里面分别配置上数据源相关参数。例如一个里面配置连接本地MySQL的参数,另一个配置连接服务器中MySQL的参数,还有一个配置连接Oracle数据库的相关参数。都准备好了以后可以通过修改中default的值来切换连接的数据库,这样要比修改里面具体的连接参数更加方便。

    6. 中type属性用于配置事务的类型。可取值:

      • JDBC:使用原生JDBC的事务管理进行提交和回滚。

      • MANAGED:MyBatis不参与事务管理。交给其他人管理事务。

    7. 中type属性值用于配置数据源类型。可取值:

      • UNPOOLED:不使用数据库连接池。每次执行SQL都会打开数据库连接,执行SQL结束都会关闭连接。适用于简单小型应用。

      • POOLED:使用MyBatis内置数据库连接池。对于频繁访问数据库的应用程序来说,这个取值是很适合的。

      • JNDI:使用本地目录接口技术连接容器外部的数据源。这种方式很少使用,一般都是极其复杂的项目,对数据源要求极高的情况下才能使用。

    8. 配置具体属性和值

      driver、url、username、password四个属性名称是固定的,但是没有顺序要求,添加到的name属性中即可。分别代表驱动类、连接字符串、用户名、密码。value属性的值为连接数据库的具体参数值。
    1. "1.0" encoding="UTF-8" ?>
    2. configuration
    3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    5. <configuration>
    6. <environments default="mysql">
    7. <environment id="mysql">
    8. <transactionManager type="JDBC">transactionManager>
    9. <dataSource type="POOLED">
    10. <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
    11. <property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"/>
    12. <property name="username" value="root"/>
    13. <property name="password" value="root"/>
    14. dataSource>
    15. environment>
    16. environments>
    17. configuration>

    4. 创建Mapper映射文件

    在src/main/resources目录中新建mybatis目录。这个文件夹可以新建也可以不建立,名称也是随意的。以后mapper文件会比较多,建立一个文件夹项目结构比较好看,名称叫做mybatis也好记。

    在mybatis文件夹下新建xml文件,文件名称随意。示例中就叫做mapper.xml

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="a.b">
    6. <insert id="addUser">
    7. insert into people values(default ,'zs','123')
    8. insert>
    9. mapper>

    5. 配置加载mapper映射文件

    映射文件是不能默认被加载的。需要在全局配置文件mybatis.cfg.xml中手动指定加载路径。

    6. 编写测试类,启动项目

    1. package com.sh;
    2. import static org.junit.Assert.assertTrue;
    3. import org.apache.ibatis.io.Resources;
    4. import org.apache.ibatis.session.SqlSession;
    5. import org.apache.ibatis.session.SqlSessionFactory;
    6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    7. import org.junit.Test;
    8. import java.io.IOException;
    9. import java.io.InputStream;
    10. /**
    11. * Unit test for simple App.
    12. */
    13. public class AppTest {
    14. /**
    15. * Rigorous Test :-)
    16. */
    17. @Test
    18. public void test1() throws IOException {
    19. // 1. 获取全局配置文件输入流
    20. InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
    21. // 2. 加载全局配置文件后创建工厂类
    22. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    23. // 3. 使用工厂创建SqlSession. 里面封装了所有增删改查的方法
    24. SqlSession session = factory.openSession();
    25. // 4. 执行sql方法,里面传递 namespace.id 通过语句的唯一标识找到sql语句
    26. int index = session.insert("a.b.addUser");
    27. System.out.println(index);
    28. // 5. mybatis是手动提交
    29. session.commit();
    30. // 6. 关闭连接,释放资源
    31. session.close();
    32. }
    33. }

    五、MyBatis属性加载

    MyBatis支持加载属性文件(.properties文件),可以通过在属性文件中配置数据库连接属性然后加载。这种方式要比直接写稍微麻烦一点点,但是却把所有的数据库连接书写到了统一的文件中,以后查看或修改时更加方便。

    1. 创建属性文件

    在src/main/resources目录中创建jdbc.properties文件

    注意:需要将$amp;转义字符变为&,否则运行报错

    1. jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
    2. jdbc.driver=com.mysql.cj.jdbc.Driver
    3. jdbc.username=root
    4. jdbc.password=root

    2. 修改全局配置文件

    修改mybatis.cfg.xml文件,设置加载属性。

    1. "1.0" encoding="UTF-8" ?>
    2. configuration
    3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    5. <configuration>
    6. <properties resource="jdbc.properties">properties>
    7. <environments default="mysql">
    8. <environment id="mysql">
    9. <transactionManager type="JDBC">transactionManager>
    10. <dataSource type="POOLED">
    11. <property name="driver" value="${jdbc.driver}"/>
    12. <property name="url" value="${jdbc.url}"/>
    13. <property name="username" value="${jdbc.username}"/>
    14. <property name="password" value="${jdbc.password}"/>
    15. dataSource>
    16. environment>
    17. environments>
    18. <mappers>
    19. <mapper resource="mybatis/mapper.xml">mapper>
    20. mappers>
    21. configuration>

    五、常见Java日志工具包

    1. 日志介绍

    日志是项目开发非常重要的一项。项目部署到服务器以后,并不能所有信息都通过控制台或命令窗口进行查看。把日志信息输入到文件中更有利于项目的维护。

    Java项目的日志是可以输入到控制台、可以输入到文件中、甚至可以输入到某个数据源中。但是常用的还是控制台和文件。

    在Java项目中常见的日志工具包:

    • Log4j:Apache推出的日志工具。于2012年5月发布1.2.17版本后停止更新。

    • Logback:属于Log4j的继承者。Spring Boot默认日志文件支持类型。

    • Log4j2:属于Log4j升级版,同时里面还包含了Logback的很多改进。

    • commons-logging:Apache早期基于门面(Facade)设计模式的日志包,提供了日志解构能力,按照顺序寻找当前项目日志接口实现,Log4j、JDK Log、SimpleLog。

    • Slf4j( Simple Logging Facade for Java ):目前使用非常多的门面日志。统一项目中日志。

    • JDK Logging:JDK自带的日志API。

    2. JDK Logging

    JDK Logging 是JDK自带的日志工具。存在于java.uti.logging包中。

    日志的级别: OFF > SEVERE > WARNING > INFO > CONFIG > FINE > FINER > FINEST > ALL

    注意:

    1. 默认级别为INFO。

    2. 只会显示该级别及该级别以上日志信息。

    1. package com.sh;
    2. import java.io.IOException;
    3. import java.util.logging.*;
    4. public class Demo {
    5. public static void main(String[] args) throws IOException {
    6. //参数通常设置为所在的类名
    7. Logger logger = Logger.getLogger("Demo");
    8. // 默认为INFO级别,同时设置当前和父处理器级别才能修改
    9. // OFF > SEVERE > WARNING > INFO > CONFIG > FINE > FINER > FINEST > ALL
    10. logger.setLevel(Level.FINEST);
    11. Handler[] handlers = logger.getParent().getHandlers();// 获取输出控制台的处理器
    12. handlers[0].setLevel(Level.FINEST);// 设置控制台输出级别
    13. // 默认没有输出到文件,只输出到控制台,通过添加Handler增加输出目的地,输出到文件中
    14. FileHandler fh = new FileHandler("my.log");// 如果路径夹会不存在文件夹会报错
    15. fh.setFormatter(new SimpleFormatter());// 设置输出内容为普通格式
    16. logger.addHandler(fh);
    17. logger.severe("severe");// 严重
    18. logger.warning("warning");// 警告
    19. logger.info("info");// 信息
    20. logger.config("config");// 配置
    21. logger.fine("fine");// 详细
    22. logger.finer("finer");// 较详细
    23. logger.finest("finest");// 非常详细
    24. }
    25. }

    3. Log4j的使用

    Log4j是Apache的开源日志工具。最新版本为2012年发布的1.2.17。

    Log4j会自动寻找classpath下log4j.properties作为配置文件。

    具体使用步骤:

    3.1 配置pom.xml
    1. <dependency>
    2. <groupId>log4jgroupId>
    3. <artifactId>log4jartifactId>
    4. <version>1.2.17version>
    5. dependency>
    3.2 编写配置文件

    在resources中新建log4j.properties,名称不要写错了。

    log4j中定义的级别:fatal(致命错误) > error(错误) > warn(警告) > info(普通信息) > debug(调试信息) > trace(跟踪信息)

    1. # log4j中定义的级别:fatal(致命错误) > error(错误) > warn(警告) > info(普通信息) > debug(调试信息) > trace(跟踪信息)
    2. # 跟日志等级为debug 使用console和file两种方式输出
    3. log4j.rootLogger = DEBUG , console , file
    4. ### console ###(日志显示在控制台的配置)
    5. log4j.appender.console = org.apache.log4j.ConsoleAppender
    6. log4j.appender.console.Target = System.out
    7. log4j.appender.console.layout = org.apache.log4j.PatternLayout
    8. log4j.appender.console.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n
    9. ### log file ###(日志输出在文件中的配置)
    10. log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
    11. # 日志输出的路径
    12. log4j.appender.file.File = log4j.log
    13. # 是否给日志文件追加
    14. log4j.appender.file.Append = true
    15. # 级别只能比根日志界别高,比根日志级别低不生效
    16. #log4j.appender.file.Threshold = info
    17. log4j.appender.file.layout = org.apache.log4j.PatternLayout
    18. log4j.appender.file.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n
    3.3 编写测试类

    注意:千万不要倒错包。

    1. package com.sh;
    2. // 不要导错包
    3. import org.apache.log4j.Logger;
    4. public class TestLog4j {
    5. public static void main(String[] args) {
    6. Logger logger = Logger.getLogger(TestLog4j.class);
    7. logger.trace("跟踪级别");
    8. logger.debug("调试信息");
    9. logger.info("普通信息");
    10. logger.warn("警告信息");
    11. logger.error("错误信息");
    12. logger.fatal("重大错误信息");
    13. }
    14. }

    4. Log4j2

    4.1 配置pom.xml

    虽然只导入了log4j-core,但是实际导入log4j-core和log4j-api。

    1. <dependency>
    2. <groupId>org.apache.logging.log4jgroupId>
    3. <artifactId>log4j-coreartifactId>
    4. <version>2.17.2version>
    5. dependency>
    4.2 编写配置文件

    Log4j2不再支持Log4j的.properties格式配置文件。而是支持.xml、.json、jsn。

    Log4j2中定义的级别:fatal(致命错误) > error(错误) > warn(警告) > info(普通信息) > debug(调试信息) > trace(跟踪信息)

    在resource目录新建log4j2.xml。

    1. "1.0" encoding="utf-8" ?>
    2. <Configuration >
    3. <Appenders>
    4. <Console name="console" target="SYSTEM_OUT">
    5. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    6. Console>
    7. <File name="file" fileName="log4j2.log" append="true">
    8. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    9. File>
    10. Appenders>
    11. <Loggers>
    12. <Root level="info">
    13. <AppenderRef ref="console"/>
    14. <AppenderRef ref="file"/>
    15. Root>
    16. Loggers>
    17. Configuration>
    4.3 编写测试类
    1. package com.bjsxt;
    2. // 千万别导错包了
    3. import org.apache.logging.log4j.LogManager;
    4. import org.apache.logging.log4j.Logger;
    5. public class TestLog4j {
    6. public static void main(String[] args) {
    7. Logger logger = LogManager.getLogger(TestLog4j.class);
    8. logger.trace("跟踪级别");
    9. logger.debug("调试信息");
    10. logger.info("普通信息");
    11. logger.warn("警告信息");
    12. logger.error("错误信息");
    13. logger.fatal("重大错误信息");
    14. }
    15. }

    5. SLF4j

    SLF4j是日志的接口声明,不参与日志的具体实现,需要配合其它日志具体实现工具包才能进行使用。

    每次添加其它日志工具包时,不要忘记SLF4j整合这个日志的依赖。

    5.1 整合Log4j
    5.1.1 导入依赖

    导入3个依赖,分别代表slf4j依赖、整合依赖、log4j的依赖。

    1. <dependency>
    2. <groupId>org.slf4jgroupId>
    3. <artifactId>slf4j-log4j12artifactId>
    4. <version>1.7.36version>
    5. dependency>
    6. <dependency>
    7. <groupId>log4jgroupId>
    8. <artifactId>log4jartifactId>
    9. <version>1.2.17version>
    10. dependency>
    5.1.2 编写log4j的配置文件

    使用写号的log4j.properties文件就行

    5.1.3 编写测试类

    小提示:

    SLF4J作为门面设计模式的具体实现,无论使用哪种日志具体实现,都是下面的API。

    1. public class TestSlf4j {
    2. public static void main(String[] args) {
    3. Logger logger = LoggerFactory.getLogger(TestSlf4j.class);
    4. logger.trace("trace");
    5. logger.debug("debug");
    6. logger.info("info");
    7. logger.warn("warn");
    8. logger.error("error");
    9. }
    10. }
    5.2 整合Log4j2
    5.2.1 配置pom.xml

    与SLF4J整合Log4j的整合包是不一样的。

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.apache.logging.log4jgroupId>
    4. <artifactId>log4j-slf4j-implartifactId>
    5. <version>2.17.2version>
    6. dependency>
    7. <dependency>
    8. <groupId>org.apache.logging.log4jgroupId>
    9. <artifactId>log4j-coreartifactId>
    10. <version>2.17.2version>
    11. dependency>
    12. dependencies>
    5.2.2 添加Log4j2的配置文件

    使用之前的log4j2.xml文件。

    5.2.3 运行测试类

    测试类的API和整合Log4j的API是完全相同的,直接运行即可。

    5.3 即整合Log4j又整合Log4j2

    SLF4J支持多种日志实现,但是在项目中整合依赖最好只有一个,否则会出现警告。

    六、MyBatis启用日志功能

    1. MyBatis支持的日志

    MyBatis框架内置日志工厂。日志工厂负责自动加载项目中配置的日志。MyBatis支持以下日志,当存在多个日志工具时,严格按照从上往下顺序使用,且只会使用一个。

    • SLF4J

    • Apache Commons Logging

    • Log4j 2

    • Log4j (deprecated since 3.5.9)

    • JDK logging

    2. MyBatis结合Log4j实现打印执行的SQL

    3. MyBatis结合Log4j2实现打印执行SQL

    同理演示Log4j2

    3.1 编写pom.xml,引入依赖
    1. <dependencies>
    2. <dependency>
    3. <groupId>org.mybatisgroupId>
    4. <artifactId>mybatisartifactId>
    5. <version>3.5.9version>
    6. dependency>
    7. <dependency>
    8. <groupId>mysqlgroupId>
    9. <artifactId>mysql-connector-javaartifactId>
    10. <version>8.0.28version>
    11. dependency>
    12. <dependency>
    13. <groupId>org.apache.logging.log4jgroupId>
    14. <artifactId>log4j-coreartifactId>
    15. <version>2.17.2version>
    16. dependency>
    17. dependencies>
    3.2 创建配置文件

    在resources目录下新建log4j2.xml文件

    1. "1.0" encoding="utf-8" ?>
    2. <Configuration >
    3. <Appenders>
    4. <Console name="Console" target="SYSTEM_OUT">
    5. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    6. Console>
    7. Appenders>
    8. <Loggers>
    9. <Root level="info">
    10. <AppenderRef ref="Console"/>
    11. Root>
    12. <logger name="a.b" level="debug">logger>
    13. Loggers>
    14. Configuration>

    4. 指定生效的日志

    在MyBatis中默认按照顺序寻找,如果项目中存在多个日志。可以通过mybatis全局配置文件进行设置哪个日志生效。

    在mybatis.cfg.xml中配置的标签

    1. "1.0" encoding="UTF-8" ?>
    2. configuration
    3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    5. <configuration>
    6. <properties resource="jdbc.properties">properties>
    7. <environments default="mysql">
    8. <environment id="mysql">
    9. <transactionManager type="JDBC">transactionManager>
    10. <dataSource type="POOLED">
    11. <property name="driver" value="${jdbc.driver}"/>
    12. <property name="url"
    13. value="${jdbc.url}"/>
    14. <property name="username" value="${jdbc.username}"/>
    15. <property name="password" value="${jdbc.password}"/>
    16. dataSource>
    17. environment>
    18. environments>
    19. <mappers>
    20. <mapper resource="mapper.xml">mapper>
    21. mappers>
    22. configuration>

    5. 测试

    1. package com.sh;
    2. import static org.junit.Assert.assertTrue;
    3. import org.apache.ibatis.io.Resources;
    4. import org.apache.ibatis.session.SqlSession;
    5. import org.apache.ibatis.session.SqlSessionFactory;
    6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    7. import org.junit.Test;
    8. import java.io.IOException;
    9. import java.io.InputStream;
    10. /**
    11. * Unit test for simple App.
    12. */
    13. public class AppTest {
    14. /**
    15. * Rigorous Test :-)
    16. */
    17. @Test
    18. public void test1() throws IOException {
    19. //1.通过流读取全局配置文件
    20. InputStream is = Resources.getResourceAsStream("mybatis_config.xml");
    21. //2.创建工厂SqlSessionFactory构建器然后创建工厂
    22. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    23. //3.通过工厂创建SqlSession
    24. SqlSession session = factory.openSession();
    25. //4.session中封装了所有的增删改查的方法
    26. int i = session.insert("a.b.add1");
    27. //验证结果
    28. System.out.println(i);
    29. //5. 增删改手动提交事务
    30. session.commit();
    31. //6. 释放资源
    32. session.close();
    33. }
    34. }

    七、SQL参数

    1. MyBatis中的占位符

    MyBatis中最常用的占位符为 #{},在MyBatis的mapper文件的SQL中使用#{}作为占位符。最终解析时会解析成JDBC的占位符?。

    2. 当参数为简单数据类型

    当参数为一个简答数据类型时。例如:八大基本数据类型、String类型等。可以通过#{任意内容}获取到。

    小提示:

    1. 任意内容代表着,随意写,只要不是特殊字符即可。

    2. 但是要注意不能不写。

    2.1 修改Test类

    SqlSession的insert()方法有两种。

    想要传递参数就需要使用insert(String,Object)的方法。

    1. @Test
    2. public void test2(){
    3. SqlSessionFactory factory = getFactory();
    4. //3.通过工厂创建SqlSession
    5. SqlSession session = factory.openSession();
    6. int i = session.insert("a.b.add2","456");
    7. System.out.println(i);
    8. session.commit();
    9. session.close();
    10. }
    1. <insert id="add2">
    2. insert into user values (default ,'ls',#{pwd})
    3. insert>

    通过使用,使用#{} 给占位赋值  先将#{}变成? 再进行解析 只有一个值需要赋值时

    #{}括号中写什么都行

    3. 当参数为多个值时 

    3.1 修改Test类

    由于insert(String,Object)方法只有一个Object类型方法能作为SQL参数,如果希望传递多个值,有两种选择:

    1.可以创建一个对应类,通过对象进行传递。

    参数是对象通过${属性名}获取

    1. @Test
    2. public void test3(){
    3. SqlSessionFactory factory = getFactory();
    4. //3.通过工厂创建SqlSession
    5. SqlSession session = factory.openSession();
    6. User user = new User();
    7. user.setUsername("zw");
    8. user.setPassword("789");
    9. int i = session.insert("a.b.add3",user);
    10. System.out.println(i);
    11. session.commit();
    12. session.close();
    13. }

    2.也可以把所有SQL参数放入到一个Map中。

    参数是Map,通过${key}获取

    1. @Test
    2. public void test3(){
    3. SqlSessionFactory factory = getFactory();
    4. //3.通过工厂创建SqlSession
    5. SqlSession session = factory.openSession();
    6. /* User user = new User();
    7. user.setUsername("zw");
    8. user.setPassword("789");*/
    9. HashMap map = new HashMap<>();
    10. map.put("username","zw");
    11. map.put("password","147");
    12. int i = session.insert("a.b.add3",map);
    13. System.out.println(i);
    14. session.commit();
    15. session.close();
    16. }
    3.2 mapper文件
    1. <insert id="add3">
    2. insert into user values (default ,#{username},#{password})
    3. insert>

    4. ${} 的使用

    在MyBatis中还有一种占位符写法:${}。

    ${}在被MyBatis进行解析时,不会解析为占位符?,而是直接解析成对应的,类似字符串拼接

    学习JDBC时我们知道SQL中存在字符串拼接时,会有SQL注入问题。

    那是不是意味着${}没有使用场景了?答案是否定的。JDBC中占位符?是不允许代替列名和表名的,也就意味着MyBatis的#{}不允许代替表名和列名但是使用${}可以动态设置列名或表名。

    ${}和#{}获取参数的写法完全相同。如果参数是对象通过${属性名}获取。如果参数是Map,通过${key}获取。如果参数是简单数据类型,通过${任意不为空的内容}进行获取。

    4.1 修改映射文件

    ${}和#{}可以混合使用。实例中使用${}代替表名。

    1. <insert id="add4">
    2. insert into ${table} values (default ,#{username},#{password})
    3. insert>
    4.2 修改Test类
    1. @Test
    2. public void test4(){
    3. SqlSessionFactory factory = getFactory();
    4. SqlSession session = factory.openSession();
    5. HashMap map = new HashMap<>();
    6. map.put("table","user");
    7. map.put("username","zw");
    8. map.put("password","258");
    9. int i = session.insert("a.b.add4", map);
    10. System.out.println(i);
    11. session.commit();
    12. session.close();
    13. }

    通过日志可以看到

    ${}直接解析为值  ,  而#{}则被解析为?

    八、MyBatis中修改和删除实现

    1. 修改和删除功能总体说明

    MyBatis实现修改和删除功能与实现新增时是非常类型的,SQL参数传递的几种方式也是相同的。

    主要区别:

    就是mapper文件中标签名不同。

    SqlSession的方法名不同。

    操作mapper标签SqlSession方法名
    新增insert(String)、insert(String,Object)
    修改update(String)、update(String,Object)
    删除delete(String)、delete(String,Object)

    2. 修改实现

    2.1 修改映射文件

    修改suiyi.xml文件.在里面添加上标签。设定使用Map进行传递参数了,所以直接使用#{key}获取到参数。

    1. <update id="update1">
    2. update user set username=#{username} where id=#{id}
    3. update>
    2.2 修改测试类
    1. @Test
    2. public void test5(){
    3. SqlSessionFactory factory = getFactory();
    4. SqlSession session = factory.openSession();
    5. HashMap map = new HashMap<>();
    6. map.put("username","hhh");
    7. map.put("id","1");
    8. int i = session.update("a.b.update1", map);
    9. System.out.println(i);
    10. session.commit();
    11. session.close();
    12. }

    3. 删除实现

    3.1 修改映射文件

    修改suiyi.xml文件.在里面添加上标签。设定使用Map进行传递参数了,所以直接使用#{key}获取到参数。

    1. <delete id="delete1">
    2. delete from user where id=#{id}
    3. delete>
    3.2 修改测试类
    1. /* 删除实现 */
    2. @Test
    3. public void test6(){
    4. SqlSessionFactory factory = getFactory();
    5. SqlSession session = factory.openSession();
    6. int i = session.delete("a.b.delete1", 10);
    7. System.out.println(i);
    8. session.commit();
    9. session.close();
    10. }

    九、MyBatis中DQL操作

    MyBatis的DQL操作在映射文件都是通过标签,resultType属性是必须写的属性。如果不写resultType属性执行时会报错。在示例中删除掉了resultType属性。

    2.1.4 查询到多行数据时

    如果使用selectOne()方法,对应的SQL查询到多行数据会报错。

    例如:修改映射文件的SQL为查询全部,且保证数据库people表有2行以上数据

    3. selectList()方法使用

    selectList()方法主要用在多行查询时,查询时把每行结果按照resultType类型进行封装,最终放入到List中。

    3.1 修改映射文件

    注意:resultType的类型为每行结果的类型,也就是List的泛型的类型。

    3.2 修改Test类
    1. //查询多个
    2. @Test
    3. public void test8(){
    4. SqlSessionFactory factory = getFactory();
    5. SqlSession session = factory.openSession();
    6. // 使用selectList方法进行查询
    7. // 返回值可以直接写映射文件中select的resultType对应类型
    8. List list = session.selectList("a.b.select2");
    9. System.out.println(list);
    10. //查询不需要事务的提交
    11. /*session.commit();*/
    12. //释放资源
    13. session.close();
    14. }

    4. selectMap()方法使用

    selectMap(String statement,Object param,String key);比上面多了String key参数。

    String key:指定查询结果中哪列的值作为map的key。map的value是整行数据,类型和resultType类型一致。

    4.1 修改映射文件
    1. <select id="select3" resultType="com.sh.util.User">
    2. select * from user
    3. select>
    4.2 修改测试类

    修改后运行效果,查看key和value的值

    1. // 使用 selectMap()
    2. @Test
    3. public void test9(){
    4. SqlSessionFactory factory = getFactory();
    5. SqlSession session = factory.openSession();
    6. // 使用selectList方法进行查询
    7. // 返回值可以直接写映射文件中select的resultType对应类型
    8. Map map = session.selectMap("a.b.select3", "id");
    9. System.out.println(map);
    10. //查询不需要事务的提交
    11. /*session.commit();*/
    12. //释放资源
    13. session.close();
    14. }

    5. selectCursor()方法使用

    cursor 表示游标。属于对查询结果集的一种遍历方式。MyBatis底层使用JDBC,在MyBatis封装的Cursor中只有遍历功能。其实就是一个一个的查询出来

    5.1 修改映射文件
    1. <select id="select4" resultType="com.sh.util.User">
    2. select * from user
    3. select>
    5.2 修改Test类

    selectCursor()返回值为Cursor,提供了forEach()遍历和iterator()两种遍历方式,下面使用forEach()遍历方式。

    1. @Test
    2. public void test10(){
    3. SqlSessionFactory factory = getFactory();
    4. SqlSession session = factory.openSession();
    5. // 使用selectList方法进行查询
    6. // 返回值可以直接写映射文件中select的resultType对应类型
    7. //泛型知道是user
    8. Cursor cursor = session.selectCursor("a.b.select4");
    9. cursor.forEach(System.out::println);
    10. //查询不需要事务的提交
    11. /*session.commit();*/
    12. //释放资源
    13. session.close();
    14. }

    6. select()方法使用

    select(String statement,Object param,ResultHandler resultHandler);方法中第三个参数表示结果处理。

    在ResultHandler接口中只有一个方法,表示如何处理

    1. //使用select
    2. //自定义查询
    3. @Test
    4. public void test11(){
    5. SqlSessionFactory factory = getFactory();
    6. SqlSession session = factory.openSession();
    7. // 使用selectList方法进行查询
    8. // 返回值可以直接写映射文件中select的resultType对应类型
    9. //该方法是自定义查询,需要重写handleResult方法,可以创建一个类继承ResultHandle来实现
    10. //也可以使用匿名内部类,这里使用内部类
    11. MyResultHandler myResultHandler = new MyResultHandler();
    12. session.select("a.b.select5",myResultHandler);
    13. //查询不需要事务的提交
    14. /*session.commit();*/
    15. System.out.println("-------------------");
    16. System.out.println(myResultHandler.getResult());
    17. //释放资源
    18. session.close();
    19. }
    20. public class MyResultHandler implements ResultHandler {
    21. HashSet set = new HashSet<>();
    22. @Override
    23. public void handleResult(ResultContext resultContext) {
    24. // System.out.println(resultContext.getResultObject());
    25. set.add(resultContext.getResultObject());
    26. }
    27. public Set getResult(){
    28. return set;
    29. }
    30. }
    31. 十、分页查询

      1. MyBatis实现分页查询的几种方式

      在MyBatis中实现查询有两种方式:

      1. 根据对应的数据库,编写SQL。这种方式与数据库耦合度较高,移植性差。但是确实我们平时使用的方式,因为大部分项目是没有修改数据库类型的场景。

      2. 使用MyBatis提供的RowBounds实现分页

      2. 根据对应数据库编写SQL

      2.1 修改映射文件
      1. <select id="select6" resultType="com.sh.util.User">
      2. select * from user limit #{index},#{size}
      3. select>
      2.2 修改测试类
      1. @Test
      2. public void test12(){
      3. SqlSessionFactory factory = getFactory();
      4. SqlSession session = factory.openSession();
      5. HashMap map = new HashMap<>();
      6. map.put("index",0);
      7. map.put("size",3);
      8. session.selectList("a.b.select6",map);
      9. System.out.println(map);
      10. //释放资源
      11. session.close();
      12. }

      这是类似JDBC的方法

      3. RowBounds方式进行分页

      RowBounds是MyBatis中提供的一种"假分页"实现方式。对从数据库中查询到的结果进行截取。所以如果数据库中数据量特别大的时候可能会出现OOM等问题。就是当查询第二页时会把第一页的数据也查询出来,但是最终只截取第二页的内容

      但是由于RowBounds不需要考虑底层数据库是什么,且使用简单,所以对于一些数据量不是特别大的应用还是有人选择使用的。

      在SqlSession中select、selectMap、selectList中通过方法重载都提供了一个带有RowBounds。

      3.1 修改映射文件
      1. <select id="select7" resultType="com.sh.util.User">
      2. select * from user
      3. select>
      3.2 修改Test类
      1. /* 使用RowBounds */
      2. @Test
      3. public void test13(){
      4. SqlSessionFactory factory = getFactory();
      5. SqlSession session = factory.openSession();
      6. //创建偏移量对象
      7. RowBounds rowBounds = new RowBounds(0, 3);
      8. //因为偏移量必须是第三个参数,再不需要给占位符赋值的时候,第二个参数也必须要写,写为null
      9. List list = session.selectList("a.b.select7", null, rowBounds);
      10. System.out.println(list);
      11. //释放资源
      12. session.close();
      13. }

      十一、模糊查询

      1. 使用#{}实现模糊查询

      1.1 修改映射文件
      1. <select id="select8" resultType="com.sh.util.User">
      2. select * from user where username like #{username}
      3. select>
      1.2 修改测试类
      1. // 模糊查询
      2. @Test
      3. public void test14(){
      4. SqlSessionFactory factory = getFactory();
      5. SqlSession session = factory.openSession();
      6. List list = session.selectList("a.b.select8","%s%");
      7. System.out.println(list);
      8. //释放资源
      9. session.close();
      10. }

    32. 相关阅读:
      Linux 命令(212)—— ssh-add 命令
      程序员还在为变量取名苦恼,那是因为你不知道,这个变量命名神器
      业绩下滑、股价大跌,芯片厂商如何越过寒冬?
      魔功心法-枚举篇
      字符串逆序 C语言
      用timerfd_*系列函数代替alarm作为定时器选项
      前端知识积累
      用pymysql封装项目通用的连接和查询
      2022年PMP考试应该注意些什么?
      大模型扫盲之小白入门手记
    33. 原文地址:https://blog.csdn.net/m0_59163770/article/details/133755571