MyBatis: 优秀的持久层框架

一、框架介绍

        把一些重复性的代码进行深度封装,在封装同时还添加了一些额外功能,这样可以写更少的代码,实现更强的功能,程序员可以将更多的精力放在业务上。这些封装随着不停的更新更迭就形成了框架(Framework),很多的框架也是开源的。

1.框架的优缺点

优点:

1.1 更好用

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

1.2 更强大

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

1.3 开发周期更短

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

缺点:

2.1 更多的学习成本

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

2.2 初学者更容易出错

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

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

        因为框架都是深度封装,对于开发者来说可能只写了一行代码,但这一行代码里面可能是几百或几千行代码的封装。一旦报错了,如果不知道框架原理是不太好解决的。所以想要更好的解决出现的问题,就必须要对每次出现的错误进行整理记忆,下次在出现这个错误的时候就可以快速解决了。

 2.Java中常见框架

Java项目无论是否使用框架,多采用MVC开发模型,一个项目被分为多层。一个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。具有权限控制时的组合。

 二、MyBatis

1.介绍

        MyBatis 是一款优秀的ORM框架,MVC分层开发中的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis可以通过简单的XML或注解来配置,把数据库和Java POJO(Plain Old Java Objects,普通老式 Java 对象)进行映射。

MyBatis中文文档地址:mybatis – MyBatis 3 | 简介

2.第一个MyBatis项目
1.创建数据库和表

在本机MySQL中创建数据库。示例数据库叫做ssm。

在ssm中创建表people。简单给people表添加两个列就行。

-- 创建数据库
create database ssm default charset utf8;
-- 使用数据库
use ssm;
-- 创建表
create table people(
	id int(11) primary key auto_increment comment '主键,自增',
	name varchar(20) not null comment '姓名'
) comment '人表';
2.常见Maven项目并添加依赖

创建一个Maven项目,并配置pom.xml。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.aaa</groupId>
    <artifactId>mybatis1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- MyBatis 框架依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
        <!-- 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
    </dependencies>

</project>
3.创建MyBatis全局配置文件

在项目的src/main/resources目录下新建mybatis.cfg.xml文件。

配置文件解释:

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

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

  3. <configuration>是根节点。

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

  5. <environment>的id值是自定义的。表示当前数据库环境的名称。在全局配置文件中<environment>标签可以有多个,里面分别配置上数据源相关参数。

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

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

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

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

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

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

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

  8. <properties>配置具体属性和值

    • driver、url、username、password四个属性名称是固定的,但是没有顺序要求,添加到<properties>的name属性中即可。分别代表驱动类、连接字符串、用户名、密码。value属性的值为连接数据库的具体参数值。4.创建Mapper映射文件

 4.创建Mapper映射文件

        在src/main/resources目录中新建+++++++++++++++++++++++++++mybatis目录。这个文件夹可以新建也可以不建立,名称也是随意的。以后mapper文件会比较多,建立一个文件夹项目结构比较好看,名称叫做mybatis也好记。在mybatis文件夹下新建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">
<mapper namespace="a.b.c">
    <insert id="add">
        insert into people values(default,'张三')
    </insert>
</mapper>

在没有和接口绑定时,namespace中内容是随意的,而且多个mapper文件的namespace可以相同的。但是不能没有namespace,值也是不能为空的。

<mapper>是根节点,必须存在的。

<insert>专门用于新增的标签

id属性值是自定义的。只要保证标签的namespace+id没有重复的就可以了

 5.加载mapper映射文件

映射文件是不能默认被加载的。需要在全局配置文件mybatis.cfg.xml中手动指定加载路径。resource取值为资源文件路径。所以每个文件夹中间是左斜杠,千万不要写成点。

 <mappers>
        <mapper resource="mybatis/suiyi.xml"/>
    </mappers>
6.编写测试类,启动项目

测试代码核心思想:MyBatis是对JDBC的封装,所有封装的方法都放入到了SqlSession类中。想要执行映射文件中SQL就必须创建SqlSession对象。

每次调用MyBatis的方法都需要创建SqlSession对象,所以MyBatis使用了工厂设计模式,由SqlSessionFactory负责创建SqlSession。

SqlSessionFactory需要加载全局配置文件,通过构造方法创建代码较负责,所以MyBatis使用了构建者设计模式,提供了更加简单的方式实例化工厂对象。

public class Test {
    public static void main(String[] args) throws IOException {
        // 1. 获取全局配置文件输入流
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        // 2. 加载全局配置文件后创建工厂类
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        // 3. 使用工厂创建SqlSession。SqlSession里面封装了所有增删改查和事务的方法。
        SqlSession session = factory.openSession();
        // 4. 执行映射文件中id="add"标签中SQL,并返回结果。如果当前项目中只有一个id="add",前面命名空间可以省略
        int index = session.insert("a.b.c.add");
        // 输出受影响行数,听过结果查看是否执行成功。
        System.out.println(index);
        // 5. 提交事务。DML操作必须提交事务,DQL不需要提交事务。
        session.commit();
        // 6. 关闭连接,释放资源
        session.close();
    }
}

三、MyBatis属性加载

        MyBatis支持加载属性文件(.properties文件),可以通过在属性文件中配置数据库连接属性然后加载。

1.创建属性文件

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

db.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
db.driver=com.mysql.cj.jdbc.Driver
db.username=root
db.password=root
 2.修改全局配置文件

修改mybatis.cfg.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>
    <!-- 加载属性文件,当前文件和db.properties在同一个目录中,使用相对路径 -->
    <properties resource="db.properties"></properties>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!-- 通过${key}获取属性文件中配置的值 -->
                <property name="driver" value="${db.driver}"/>
                <property name="url" value="${db.url}"/>
                <property name="username" value="${db.username}"/>
                <property name="password" value="${db.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mybatis/suiyi.xml"/>
    </mappers>
</configuration>

 四、常见Java日志工具包

1.日志介绍

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

在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. 只会显示该级别及该级别以上日志信息。

 3.Log4j的使用

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

1.配置pom.xml
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
2.编写配置文件

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

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

# log4j中定义的级别:fatal(致命错误) > error(错误) > warn(警告) > info(普通信息) > debug(调试信息) > trace(跟踪信息)
log4j.rootLogger = DEBUG , console , file

### console ###(日志显示在控制台的配置)
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n

### log file ###(日志输出在文件中的配置)
log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File = D:/log4j.log
log4j.appender.file.Append = true
# 级别只能比根日志界别高,比根日志级别低不生效
#log4j.appender.file.Threshold = info 
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n
 3.编写测试类
import org.apache.log4j.Logger;

public class TestLog4j {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(TestLog4j.class);
        logger.trace("跟踪级别");
        logger.debug("调试信息");
        logger.info("普通信息");
        logger.warn("警告信息");
        logger.error("错误信息");
        logger.fatal("重大错误信息");
    }
}
4.Log4j2
1.配置pom.xml

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

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
</dependency>
2.编写配置文件

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

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

在resource目录新建log4j2.xml。

<?xml version="1.0" encoding="utf-8" ?>
<Configuration >
    <!-- 定义输出的目的地 -->
    <Appenders>
        <!-- Console 定义控制台输出 name:自定义名称 target:输出方式,支持SYSTEM_OUT SYSTEM_ERR -->
        <Console name="console" target="SYSTEM_OUT">
            <!-- 输出信息表达式 -->
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <!-- File 定义文件输出 fileName 文件路径  append是否允许追加 -->
        <File name="file" fileName="D:/log4j2.log" append="true">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </File>
    </Appenders>

    <Loggers>
        <!-- 控制总体级别 -->
        <!-- fatal > error > warn > info > debug > trace -->
        <Root level="info">
            <!-- 引用输出位置的配置,Appenders中直接子标签的name属性值 -->
            <AppenderRef ref="console"/>
            <AppenderRef ref="file"/>
        </Root>
    </Loggers>
</Configuration>
3.编写测试类
// 千万别导错包了
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class TestLog4j {
    public static void main(String[] args) {
        Logger logger = LogManager.getLogger(TestLog4j.class);
        logger.trace("跟踪级别");
        logger.debug("调试信息");
        logger.info("普通信息");
        logger.warn("警告信息");
        logger.error("错误信息");
        logger.fatal("重大错误信息");
    }
}
5.SLF4j

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

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

 1.整合Log4j
<!--slf4j整合log4j的依赖,版本要和slf4j的版本对应 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.36</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
2.编写log4j的配置文件

在resources下新建log4j.properties文件。

3.编写测试类
public class TestSlf4j {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(TestSlf4j.class);

        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
        logger.warn("warn");
        logger.error("error");
    }
}
6.MyBatis结合Log4j2实现打印SQL
1.编写pom.xml
<dependencies>
    <!-- MyBatis 框架依赖 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.9</version>
    </dependency>
    <!-- 数据库驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.28</version>
    </dependency>
    <!-- log4j2 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.17.2</version>
    </dependency>
</dependencies>
2.创建配置文件

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

<?xml version="1.0" encoding="utf-8" ?>
<Configuration >
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
        <!-- namespace的值 -->
        <logger name="a.b.c" level="debug"></logger>
    </Loggers>
</Configuration>
3.指定生效日志

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

<?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>
    <properties resource="jdbc.properties">
        <property name="mykey" value="com.mysql.cj.jdbc.Driver"/>
    </properties>
    <!-- 位置为properties下面,typeAlias的上面,具体可以Ctrl+mybatis-3-config.dtd查看 -->
    <settings>
        <!-- 配置生效的日志 -->
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <environments default="suiyi1">
        <environment id="suiyi1">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${mykey}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mybatis/suiyi.xml"></mapper>
        <mapper resource="mybatis/suiyi2.xml"></mapper>
    </mappers>
</configuration>

五、SQL参数

1.MyBatis中占位符

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

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

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

1.修改Test类

 SqlSession的insert()方法有两种。

int insert(String statement);// 参数:调用SQL的名称。a.b.c.add
int insert(String statement, Object parameter);// 第一个参数:调用SQL的名称。第二个参数:参数值

修改Test类中代码,传递参数值给mapper文件中的SQL。

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        // 给定了insert方法的第二个参数。
        int index = session.insert("a.b.c.add","参数值");
        System.out.println(index);
        session.commit();
        session.close();
    }
}
 2.修改mapper文件内容

SQL语句中使用#{}获取Test类中传递过来的参数值。

<?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">
<mapper namespace="a.b.c">
    <insert id="add">
        insert into people values(default,#{suiyixie})
    </insert>
</mapper>
3.观察打印的SQL

发现控制台打印的SQL中#{}会被解析为JDBC的占位符?

占位符的值为Test类中insert方法第二个参数的值。

 

 3.当参数为对象类型参数
1.创建实体类
2.修改Test类

设置SqlSession的insert方法第二个参数值为一个对象。

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        // 给定了insert方法的第二个参数为对象。
        People peo = new People();
        peo.setId(123);
        peo.setName("名字");
        int index = session.insert("a.b.c.add",peo);
        System.out.println(index);
        session.commit();
        session.close();
    }
}
3.修改mapper文件内容

当参数对象类型时,可以使用#{对象中属性名}获取对象属性值。

<?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">
<mapper namespace="a.b.c">
    <insert id="add">
        insert into people values(#{id},#{name})
    </insert>
</mapper>
4.${}使用
1.介绍

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

${}在被MyBatis进行解析时,不会解析为占位符?,而是直接解析成对应的值。也就是说使用${}时有点类似字符串拼接。

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

 2.#{}和${}的区别

#{}被解析为?,用在设置列的值或条件值时,也可以使用在分页等需要设置具体值的情况。

${}表示字符串拼接,用在动态设置表名和动态设置列名的情况下。

六、MyBatis中修改和删除实现

1.总体说明

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

主要区别:

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

SqlSession的方法名不同。

操作mapper标签SqlSession方法名
新增<insert>insert(String)、insert(String,Object)
修改<update>update(String)、update(String,Object)
删除<delete>delete(String)、delete(String,Object)
 2.修改实现
1.修改映射文件
修改suiyi.xml文件.在里面添加上<update>标签。设定使用Map进行传递参数了,所以直接使用#{key}获取到参数。
<?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">
<mapper namespace="a.b.c">
    <insert id="add">
        insert into people values(#{id},#{name})
    </insert>
    <!-- 修改功能 -->
    <update id="update">
        update people set name=#{name} where id=#{id}
    </update>
</mapper>
 2.修改测试类

和新增的代码主要区别:

session的insert()方法换成update()方法。

update()方法第一个参数变成了mapper中update标签的路径。

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        // map对象里面放了所有需要传递给SQL的参数
        Map<String,Object> param = new HashMap<>();
        param.put("id",234);
        param.put("name","名字-update");// 随意设置个修改的值
        //int index = session.insert("a.b.c.add",param);
        //方法名由insert换成update。修改里面的statement字符串为namespace+mapper中update标签id值
        int index = session.update("a.b.c.update",param);
        System.out.println(index);
        session.commit();
        session.close();
    }
}
3.删除实现

删除与修改类似。

七、MyBatis中DQL操作

1.总体说明

MyBatis的DQL操作在映射文件都是通过<select>标签实现的。

SqlSession根据根据查询结果类型不同,提供了五种查询方法:

方法名解释说明
selectOne()查询一行数据时,返回值为Object。如果没有查询到,但是不能查询到多行。
selectMap()查询多行数据时,把其中某列结果当做key,每行结果为Value
selectList()当查询多行数据时,返回值为List。如果没有查询到返回长度为零的List对象。
selectCursor()使用游标查询时使用,在大量数据时可以代替分页
select()万能方法,需要自己定义结果处理器
2.SelectOne()方法使用

 selectOne()方法要求查询结果是一行或没有查询到。如果查询结果是多行会报异常。

1.修改映射文件

在映射中添加<select>标签,resultType属性是<select>标签必须有的属性,表示查询结果最终类型。取值为类型的全限定路径。

 <!-- 必须保证列名和resultType中类型的属性名相同才能保证把查询结果放入到对应的对象中-->
    <select id="one" resultType="People">
        select * from people where id=#{id}
    </select>
 2.修改测试类

selectOne()方法返回值是泛型类型,所以可以直接写对应的类型。

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        Map<String,Object> param = new HashMap<>();
        param.put("id",1);
        // 使用selectOne方法进行查询
        // 返回值可以直接写映射文件中select的resultType对应类型
        People peo = session.selectOne("a.b.c.one",param);
        System.out.println(peo);// 如果没有查询到输出null
        session.commit();
        session.close();
    }
}
3.selectList()方法使用

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

 1.修改映射文件
<!-- DQL:selectList -->
    <select id="map" resultType="People">
        select * from people
    </select>
2.修改测试类

如果没有查询到结果,返回长度为0的集合,而不是null

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        Map<String,Object> param = new HashMap<>();
        param.put("id",1);
        // 返回值List的泛型写resultType对应类型
        // 参数传递过去,但是在SQL中没有使用
        List<People> list = session.selectList("a.b.c.list", param);
        session.commit();
        session.close();
    }
}
4.SelectMap()方法使用
1.修改映射文件
<!-- DQL:selectMap -->
    <select id="map" resultType="People">
        select * from people
    </select>
2.修改测试类

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

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        Map<String,Object> param = new HashMap<>();
        param.put("id",1);
        // 第三个参数:查询到的name值当做key
        Map<String, People> map = session.selectMap("a.b.c.map", param, "name");
        System.out.println(map);
        session.commit();
        session.close();
    }
}
5.selectCursor()方法使用

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

 1.修改映射文件
 <!-- DQL:selectCursor -->
    <select id="cursor" resultType="People">
        select * from people
    </select>
2.修改Test类

selectCursor()返回值为Cursor,提供了forEach()遍历和iterator()两种遍历方式,下图演示forEach()遍历方式。

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        Map<String,Object> param = new HashMap<>();
        param.put("id",1);
        // 返回游标
        Cursor<People> cursors = session.selectCursor("a.b.c.cursor", param);
        // 遍历游标
        cursors.forEach(System.out::println);
        session.commit();
        session.close();
    }
}

 九、分页查询

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

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

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

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

1.SQL实现分页 
1.实现映射修改
<!-- 根据数据库类型,编写对应的SQL -->
    <select id="page" resultType="People">
        select * from people limit #{pageStart},#{pageSize}
    </select>
2.修改测试类
public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        Map<String,Object> param = new HashMap<>();
        param.put("pageStart",0);
        param.put("pageSize",2);

        // 分页查询返回数据为多行,所以多结合selectList一起使用
        List<People> list = session.selectList("a.b.c.page", param);
        System.out.println(list);

        session.commit();
        session.close();
    }
}
2.RowBounds方式进行分页
1.修改映射
 <!-- 使用RowBounds -->
    <select id="rowBounds" resultType="People">
        select * from people
    </select>
2.修改测试类
public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();

        // RowBounds(偏移量,查询行数)
        RowBounds rowBounds = new RowBounds(0,2);
        List<People> list = session.selectList("a.b.c.rowBounds",null,rowBounds);
        System.out.println(list);

        session.commit();
        session.close();
    }
}

十、模糊查询

1.使用#{}实现模糊查询
1.修改映射文件
<!-- 模糊查询 -->
    <select id="like" resultType="People">
        select * from people where name like #{name}
    </select>
2.修改测试类
public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();

        // 参数的值里面包含了%
        List<People> list = session.selectList("a.b.c.like", "%张%");
        System.out.println(list);

        session.commit();
        session.close();
    }
}
2.使用${}实现模糊查询
1.在映射文件中添加新的方法

使用${}时由于是字符串拼接,所以两侧需要带有双引号。

这种方式的SQL比较固定,两侧%已经写到SQL中,不能像#{}形式动态设置是包含、开头、结尾等形式的模糊查询。

  <!-- 模糊查询 -->
    <select id="like2" resultType="People">
        select * from people where name like '%${name}%'
    </select>
 2.修改实现类
public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();

        // 参数的值不需要包含%了
        List<People> list = session.selectList("a.b.c.like2", "张");
        System.out.println(list);

        session.commit();
        session.close();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值