自学内容网 自学内容网

Java mybatis day1015

ok了家人们,今天学习了mybatis这个框架,我们一起去看看吧

.Mybatis简介

1.1 Mybatis概述

MyBatis 最初是 Apache 的一个开源项目 iBatis, 2010 6
这个项目由 Apache Software Foundation 迁移到了
Google Code 。随着开发团队转投 Google Code 旗下,
iBatis3.x 正式更名为 MyBatis 。代码于 2013 11 月迁移到
Github
MyBatis 是一款优秀的持久层框架,用于简化 JDBC
发。它支持自定义 SQL 、存储过程以及高级映射。
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获
取结果集的工作。 MyBatis 可以通过简单的 XML 或注解来
配置和映射原始类型、接口和 Java POJO Plain Old Java
Objects ,普通老式 Java 对象)为数据库中的记录。
官网: https://mybatis.org/mybatis-3/zh/index.html

1.2 浅谈JDBC代码

public class DemoTest {
    public static void main(String[] args) {
    //1. 注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    //2. 获取Connection连接
    String url = "jdbc:mysql:///db1? useSSL=false";
    String uname = "root";
    String pwd = "1234";
    Connection conn =
    DriverManager.getConnection(url, uname, pwd);
    // 接收输入的查询条件
    String gender = "男";
    // 定义sql
    String sql = "select * from tb_user where gender = ?";
    // 获取pstmt对象
    PreparedStatement pstmt =
                    conn.prepareStatement(sql);
    // 设置?的值
    pstmt.setString(1,gender);
    // 执行sql
    ResultSet rs = pstmt.executeQuery();
    // 遍历Result,获取数据
    User user = null;
    ArrayList<User> users = new ArrayList<>();
    while (rs.next()) {
    //获取数据
    int id = rs.getInt("id");
    String username =
    rs.getString(“username”);
    String password =
    rs.getString(“password”);
    //创建对象,设置属性值
    user = new User();
    user.setId(id);
    user.setUsername(username);
    user.setPassword(password);
    user.setGender(gender);
    //装入集合
    users.add(user);
    }
    //释放资源
    rs.colse();
    pstmt.colse();
    conn.close();
    }
}

  • 硬编码
注册驱动、获取连接。连接数据库的四个基本信息,以
后如果要将 Mysql 数据库换成其他的关系型数据库的
话,这四个地方都需要修改,如果放在此处就意味着要
修改我们的源代码。
如果表结构发生变化, SQL 语句就要进行更改。这也不
方便后期的维护。
  • 操作繁琐
手动设置参数
手动封装结果集
MyBatis SQL Java 编码分开,功能边界清晰。 Java 代码专
注业务、 SQL 语句专注数据
MyBatis :免除了几乎所有的 JDBC 代码以及设置参数和获取
结果集的工作

1.3 框架名词解释

  • 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
  • 在框架的基础之上构建软件编写更加高效、规范、通用、
    可扩展

.快速入门(基于Mybatis3式)

2.1 入门案例实现步骤

  • 创建数据库和表
  • 创建模块,导入坐标
  • 实体类准备
  • 编写Mybatis核心配置文件
  • 编写Mapper接口
  • 编写 SQL 映射文件
  • 测试

创建数据库和表

CREATE TABLE t_emp(
emp_id INT primary key AUTO_INCREMENT,
emp_name CHAR(100),
emp_salary DOUBLE(10,5)
);
INSERT INTO t_emp(emp_name,emp_salary)
VALUES("张三",200.33);
INSERT INTO t_emp(emp_name,emp_salary)
VALUES("李四",200.44);
INSERT INTO t_emp(emp_name,emp_salary)
VALUES("王五",200.55);
创建模块,导入坐标
<dependencies>
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<!-- MySQL驱动 mybatis底层依赖jdbc驱动实现,本次
不需要导入连接池,mybatis自带! -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connectorjava</artifactId>
<version>8.0.25</version>
</dependency>

<!--junit5测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiterapi</artifactId>
<version>5.3.1</version>
</dependency>
</dependencies>
实体类准备
public class Employee {
private Integer empId;
private String empName;
private Double empSalary;
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Double getEmpSalary() {
return empSalary;
}
public void setEmpSalary(Double empSalary) {
this.empSalary = empSalary;
}
@Override
public String toString() {
return "Employee{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", empSalary=" + empSalary +
'}';
}
}
编写 Mybatis 核心配置文件
  • 替换连接信息 解决硬编码问题
  • 在模块下的 resources 目录下创建 mybatis 的配置文件
    mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config
3.0//EN"
"https://mybatis.org/dtd/mybatis-3-
config.dtd">
<!--configuration表示mybatis框架的核心配置文件的根标
签,配置-->
<configuration>
<!--
environments:表示当前mybatis框架的环境:开发
测试环境等
一个environments标签下面可以书写多个
environment
一个environment标签代表一个环境
-->
<environments default="development">
<environment id="development">
<!--
事务管理,这里先使用mybatis框架的默认
管理type="JDBC",实际开发中
mybatis框架的事务由spring框架
-->
<transactionManager type="JDBC">
</transactionManager>
<!--

-->
<dataSource type="POOLED">
<property name="driver"
value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/ssm_01"/>

<property name="username"
value="root"/>
<property name="password"
value="123456"/>
</dataSource>
</environment>
</environments>
<!--加载映射配置文件-->
<mappers>
<mapper resource="EmployeeMapper.xml">
</mapper>
</mappers>
</configuration>

编写Mapper接口

Mybatis 中的 Mapper 接口相当于以前的 Dao 。但是区别在
于, Mapper 仅仅只是建接口
package com.lzw.mapper;
import com.lzw.pojo.Employee;
import java.util.List;
//接口只规定方法,参数和返回值!映射配置文件中编写具体SQL
语句!
public interface EmployeeMapper {
public List<Employee> findAll();
}
编写 SQL 映射文件
  • 统一管理sql语句,解决硬编码问题
  • 在模块的 resources 目录下创建映射配置文件
    EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper
3.0//EN"
"https://mybatis.org/dtd/mybatis-3-
mapper.dtd">
<!--namespace:名称空间 该映射配置文件和哪个Mapper接口
进行映射绑定-->
<mapper
namespace="com.lzw.mapper.EmployeeMapper">
<!--
id:唯一标识,映射接口的方法
resultType:输出的参数类型
-->
<select id="findAll"
resultType="com.lzw.pojo.Employee">
select emp_id empId,emp_name
empName,emp_salary empSalary from t_emp
</select>
</mapper>
测试
public class DemoTest {
//入门案例
@Test
public void test01() throws IOException {
//读取核心配置文件
InputStream in =
Resources.getResourceAsStream("mybatisconfig.xml");
//构建SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(in);
//通过SqlSessionFactory工厂对象获取SqlSession对象(就是connection)
SqlSession sqlSession =
sqlSessionFactory.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
List<Employee> employeeList =
employeeMapper.findAll();
//处理结果
for (Employee employee : employeeList) {
System.out.println(employee);
}
//释放资源
sqlSession.close();
}
}

2.2 Lombok插件的使用(简化代码)

使用 Lombok 注解就可以省略生成 getXxx() setXxx() 方法、
toString() 方法、构造器等固定格式代码的繁琐操作,提高开
发效率。包括 Logger 日志对象。
Lombok 原理: Lombok 是将自动生成的代码织入字节码文件
中,从而实现:源代码没有,但是字节码文件有 —— 毕竟我们
最终运行的是字节码文件,只要字节码文件中有即可。而这个
过程因为要参与源文件编译,所以需要安装 IDEA 插件。
Lombok 安装
加入依赖
  <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
注解功能介绍
注解
作用
@Data
生成 getXxx() 方法、 setXxx()
法、 toString() equals()
canEqual() hashCode() 方法
@AllArgsConstructor
生成全参构造器
@NoArgsConstructor
生成无参构造器
@Slf4j
生成日志对象
@Getter
生成 getXxx() 方法
@Setter
生成 setXxx() 方法
@ToString
生成 toString() 方法
使用 Lombok
package com.cjx.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    private Integer empId;
    private String empName;
    private Double empSalary;
}

2.3 日志框架(便于调试)

2.3.1 用日志打印替代sout
sout 有什么问题
System.out 对象是一个输出流对象,所以控制台输出信息
本质上是 I/O 操作。而 I/O 操作是项目运行过程中两大性能
瓶颈之一。
项目上线时,希望把所有(或一部分) sout 打印关闭,但
是只能手动一个一个查找,耗费开发人员的极大精力,因
sout 的无度使用会使它分散在项目的各个角落。
使用 [ 日志框架 ] 的好处
设定级别,统一管理。日志框架会按照事件的严重程度来
划分级别,例如:
        错误(Error ):表示程序运行出错,比如抛异常等情
        况。
        警告(Warning ):表示程序运行过程中有潜在风险,
        但此时并没有报错。
        信息(Info ):表示程序运行过程中完成了一个关键动
        作,需要以程序运行信息的形式告知开发者。
        调试(Debug ):表示程序运行过程中更加细致的信
        息,协助程序员调试程序。
灵活指定输出位置
        使用日志框架不一定是打印到控制台,也可以保存到文
        件中或者保存到数据库。这就看具体的项目维护需求。
自定义日志格式
        打印日志数据可以使用日志框架的默认格式,也可以根
        据需要定制。
基于日志分析问题
        将来我们开发的应用系统中,不仅包含Java 代码,还有
        很多中间件服务器。任何子系统出现故障我们都是通过
        日志来定位问题、分析故障原因。甚至更复杂的系统还
        会专门开发日志子系统,在主系统出现问题时抓取日志
        数据供维护人员参考。而日志数据必须要有确定格式才
        便于格式化和抓取,这肯定不是随意写sout 就能实现
        的。
通过在配置文件中指定某一个日志级别来控制系统要打印的内
容。日志框架会打印 当前指定级别 的日志和比当前指定级别
严重 的级别的日志。
例如在开发阶段,我们指定 debug 级别,项目上线修改成 info
级别,那么所有 debug 级别的日志就都不打印了,不需要到项
目代码中一个一个修改,非常方便。
2.3.2 Java日志体系演变

门面:类似于标准层、接口层

名称
说明
JCL Jakarta Commons Logging
陈旧
SLF4J Simple Logging Facade for Java)
适合( 同一作
jboss-logging
特殊专业领域使用

实现
名称
说明
log4j
最初版( 同一作者
JUL
java.util.logging
JDK 自带
log4j2
Apache 收购 log4j 后全面重构,
内部实现和 log4j 完全不同
logback
优雅、强大( 同一作者
最佳拍档
  • 门面:SLF4J
  • 实现:logback
2.3.3 日志用法
  • 依赖导入
<!-- 日志 会自动传递slf4j门面-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
  • 引入配置
Logback 要求配置文件名称必须是 logback.xml ,存放路径在
main/resources 目录下。
通过配置文件,可以配置输出格式、输出级别、输出位置等!
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 指定日志输出的位置,ConsoleAppender表示输出
到控制台 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志输出的格式 -->
<!-- 按照顺序分别是:时间、日志级别、线程
名称、打印日志的类、日志主体内容、换行 -->
<pattern>[%d{HH:mm:ss.SSS}]
[%-5level] [%thread] [%logger]
[%msg]%n</pattern>
<charset>UTF-8</charset>
</encoder>
2.4 工具类抽取(简化代码)
</appender>
<!-- 设置全局日志级别。日志级别按顺序分别是:
TRACE、DEBUG、INFO、WARN、ERROR -->
<!-- 指定任何一个日志级别都只打印当前级别和后面级别
的日志。 -->
<root level="DEBUG">
<!-- 指定打印日志的appender,这里通
过“STDOUT”引用了前面配置的appender -->
<appender-ref ref="STDOUT" />
</root>
<!-- 根据特殊需求指定局部日志级别,可也是包名或全类
名。 -->
<logger name="com.lzw.mapper" level="DEBUG"
/>
</configuration>

2.4 工具类抽取(简化代码)

package com.cjx.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionUtil {
    private static SqlSessionFactory sqlSessionFactory=null;
    static {
        try {
            //读取核心配置文件
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            //构建SqlSessionFactory工厂对象
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession openSession(){
    //通过SqlSessionFactory工厂对象获取SqlSession对象(就是connection)
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }
}

package com.cjx.test;

import com.cjx.mapper.EmployeeMapper;
import com.cjx.pojo.Employee;
import com.cjx.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class DemoTest {
    //查询所有
    @Test
    public void test01(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        List<Employee> employeeList = employeeMapper.findAll();
        //处理结果
        for (Employee employee : employeeList) {
            System.out.println(employee);
        }
        //释放资源
        sqlSession.close();
    }

2.5 增删改查

  • Mapper接口
package com.cjx.mapper;

import com.cjx.pojo.Employee;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface EmployeeMapper {
    //查询所有数据
    List<Employee> findAll();
    //查询单个数据
    Employee findEmpById(Integer empId);
    //添加一条数据
    public Integer insertEmp(Employee employee);
    //修改一条数据
    public Integer updateEmp(Employee employee);
    //删除一条数据
    public Integer deleteEmpById(Integer empId);
    //修改一条数据 零散的简单类型数据
    public Integer updateEmpById(@Param("empName") String empName,@Param("empSalary") double empSalary,@Param("empId") Integer empId);
    //修改一条数据
    public Integer update(Map<String,Object> map);
}
  • 映射配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace:名称空间 接口的全限定名-->
<mapper namespace="com.cjx.mapper.EmployeeMapper">
    <!--id:唯一标识 接口的方法名保持一致-->
    <!--结果类型:如果是集合 写集合的元素的类型-->
    <select id="findAll"  resultType="Employee">
        select * from t_emp
    </select>

    <select id="findEmpById" parameterType="int" resultType="Employee">
        select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}
    </select>

    <insert id="insertEmp">
        insert into t_emp values(null,#{empName},#{empSalary})
    </insert>

    <update id="updateEmp">
        update t_emp set emp_name=#{empName},emp_salary=#{empSalary} where emp_id=#{empId}
    </update>

    <delete id="deleteEmpById" parameterType="int">
        delete from t_emp where emp_id=#{empId}
    </delete>

    <update id="updateEmpById">
        update t_emp set emp_name=#{empName},emp_salary=#{empSalary} where emp_id=#{empId}
    </update>

    <update id="update" parameterType="Map">
        update t_emp set emp_name=#{empName},emp_salary=#{empSalary} where emp_id=#{empId}
    </update>
</mapper>
  • 测试
package com.cjx.test;

import com.cjx.mapper.EmployeeMapper;
import com.cjx.pojo.Employee;
import com.cjx.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class DemoTest {
    //查询所有
    @Test
    public void test01(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        List<Employee> employeeList = employeeMapper.findAll();
        //处理结果
        for (Employee employee : employeeList) {
            System.out.println(employee);
        }
        //释放资源
        sqlSession.close();
    }

    //通过Id查询数据
    @Test
    public void test02(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        Employee emp = employeeMapper.findEmpById(1);
        //处理结果
        System.out.println(emp);
        //释放资源
        sqlSession.close();
    }

    //新增一条数据
    @Test
    public void test03(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        Employee employee = new Employee(null,"赵六",260.0);
        Integer emp = employeeMapper.insertEmp(employee);
        //处理结果
        System.out.println(emp);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

    //修改一条数据根据Id
    @Test
    public void test04(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        Employee employee = new Employee(1,"zs",230.0);
        Integer emp = employeeMapper.updateEmp(employee);
        //处理结果
        System.out.println(emp);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

    //删除一条数据根据Id
    @Test
    public void test05(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        Integer emp = employeeMapper.deleteEmpById(4);
        //处理结果
        System.out.println(emp);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }
    //修改一条数据根据Id
    @Test
    public void test07(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        Integer emp = employeeMapper.updateEmpById("ww",255.55,3);
        //处理结果
        System.out.println(emp);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }
    //修改一条数据根据Id
    @Test
    public void test06(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        Map<String,Object> map = new HashMap<>();
        map.put("empName","ls");
        map.put("empSalary",244.44);
        map.put("empId",2);
        Integer emp = employeeMapper.update(map);
        //处理结果
        System.out.println(emp);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }
}
  • 注意事项
插入操作涉及数据库数据变化,所以要使用 sqlSession 对象显
示的提交事务,即 sqlSession.commit()
增删改接口的返回值是 Integer, 表示返回影响的行数 , 在映射配
置文件中不需要设置 resultType

. MyBatis核心配置文件

MyBatis 的核心配置文件包含了会深深影响 MyBatis 行为的
设置和属性信息。 配置文档的顶层结构如下:
  • configuration(配置)
    • properties(属性)
    • settings(设置)
    • typeAliases(类型别名)
    • typeHandlers(类型处理器)
    • objectFactory(对象工厂)
    • plugins(插件)
    • environments(环境配置)
      • environment(环境变量)
        • transactionManager(事务管理器)
        • dataSource(数据源)
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器)
注意事项:在配置时按照以上顺序进行配置

3.1 properties(属性)

实际开发中,习惯将数据源的配置信息单独抽取成一个
properties 文件,该标签可以加载额外配置的 properties
件。
  • db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_01
jdbc.username=root
jdbc.password=123456
  • mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <!--加载外部properties-->
    <properties resource="db.properties"></properties>
    <!--开启自动映射 驼峰命名-->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--起别名-->
    <typeAliases>
        <package name="com.cjx.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--8.x-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--5.x-->
                <!-- <property name="driver" value="com.mysql.jdbc.Driver"/>-->

                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--核心配置文件加载映射配置文件-->
    <mappers>
        <mapper resource="EmployeeMapper.xml"/>
    </mappers>
</configuration>

3.2 settings(设置)

设置名
描述
mapUnderscoreToCamelCase
是否开启驼峰命名自动
映射,即从经典数据库
列名 A_COLUMN 映射
到经典 Java 属性名
aColumn 。 取值: true
| false 默认值: false
<!--开启驼峰映射-->
<settings>
<setting name="mapUnderscoreToCamelCase"
value="true"/>
</settings>

3.3 typeAliases(类型别名)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML
配置,意在降低冗余的全限定类名书写。
 <typeAliases>
        <package name="com.cjx.pojo"/>
    </typeAliases>

3.4 environments(环境配置)

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL
映射应用于多种数据库之中, 现实情况下有多种理由需要这
么做。例如,开发、测试和生产环境需要有不同的配置。
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--8.x-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--5.x-->
                <!-- <property name="driver" value="com.mysql.jdbc.Driver"/>-->

                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

.数据输入

  • 简单类型:只包含一个值的数据类型
    • 基本数据类型:intbyteshortdouble……
    • 基本数据类型的包装类型:IntegerCharacterDouble……
    • 字符串类型:String
  • 复杂类型:包含多个值的数据类型
    • 实体类类型:EmployeeDepartment……
    • 集合类型:ListSetMap……
    • 数组类型:int[]String[]……
    • 复合类型:List<Employee>、实体类中包含集合……

4.1 参数占位符

#{} :执行 SQL 时,会将 #{} 占位符替换为?,将来自动设
置参数值。从案例可以看出使用 #{} 底层使用的是
PreparedStatement
public interface EmployeeMapper {
//查询单个数据
public Employee findEmpById01(Integer
empId);
}
<select id="findEmpById01" parameterType="int"
resultType="Employee">
select * from t_emp where emp_id = #{empId}
</select>

${} :拼接 SQL 。底层使用的是 Statement ,会存在 SQL 注入问题
public interface EmployeeMapper {
//查询单个数据
public Employee findEmpById02(Integer
empId);
}
<select id="findEmpById02" parameterType="int"
resultType="Employee">
select * from t_emp where emp_id = ${empId}
</select>

结论:实际开发中,能用 #{} 实现的,肯定不用 ${}

4.2 parameterType使用

对于有参数的 mapper 接口方法,我们在映射配置文件中应该
配置 ParameterType 来指定参数类型。只不过该属性都可以
省略。
<insert id="insertEmp" parameterType="Employee">
insert into t_emp values(null,#{empName},#
{empSalary})
</insert>

4.3 单个简单类型参数

4.3.1 编写接口方法
public interface EmployeeMapper {
//删除一条数据
public Integer deleteEmpById(Integer empId);
}
4.3.2 编写SQL语句
<delete id="deleteEmpById"
parameterType="java.lang.Integer">
delete from t_emp where emp_id = #{empId}
</delete>
  • 增删改接口的返回值是 Integer, 表示返回影响的行数 , 在映
    射配置文件中不需要设置 resultType
  • 单个简单类型参数,在 #{} 中可以随意命名,但是没有必
    要。通常还是使用和接口方法参数同名。
4.3.3 编写测试方法
 //删除一条数据根据Id
    @Test
    public void test05(){
        //获取SqlSession
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //基于接口获取实现类对象(代理对象)
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //通过多态调用方法
        Integer emp = employeeMapper.deleteEmpById(4);
        //处理结果
        System.out.println(emp);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

4.4 实体类类型参数

将多个参数封装成一个 实体对象 ,将该实体对象作为接口的
方法参数。该方式要求在映射配置文件的 SQL 中使用 #{ 内容 }
时,里面的内容必须和实体类属性名保持一致。
4.4.1 编写接口方法
public interface EmployeeMapper {
//添加一条数据
public Integer insertEmp(Employee employee);
}
4.4.2 编写SQL语句
<!--实体传参,在映射配置文件中取值,直接写对象的属性名-->
<insert id="insertEmp" parameterType="Employee">
insert into t_emp values(null,#{empName},#
{empSalary})
</insert>
4.4.3 编写测试方法
@Test
public void testInsert(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
Employee employee=new Employee(null,"王五",555.22);
Integer row = employeeMapper.insertEmp(employee);
//输出结果
System.out.println(row);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}

4.5 零散的简单类型数据

零散的多个简单类型参数,如果没有特殊处理,那么 Mybatis
无法识别自定义名称:
4.5.1 编写接口方法
public interface EmployeeMapper {
//根据ID修改员工姓名
public Integer updateNameById(String
empName,Integer empId);
}
4.5.2 编写SQL语句
<update id="updateNameById">
update t_emp set emp_name = #{empName} where
emp_id = #{empId}
</update>
4.5.3 编写测试方法
@Test
public void testupdateNameById(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
Integer row =
employeeMapper.updateNameById("zs",1);
//输出结果
System.out.println(row);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}

4.5.4 解决方案
  • 修改配置文件取值方式
<update id="updateNameById">
update t_emp set emp_name = #{param1} where
emp_id = #{param2}
</update>
  • 使用 @Param(" 参数名称 ") 标记每一个参数,在映射配置
    文件中就需要使用 #{ 参数名称 } 进行占位
public interface EmployeeMapper {
//根据ID修改员工姓名
public Integer
updateNameById(@Param("empName") String empName,
@Param("empId") Integer empId);
}
<update id="updateNameById">
update t_emp set emp_name = #{empName} where
emp_id = #{empId}
</update>

4.6 Map类型参数

将多个参数封装到 map 集合中,将 map 集合作为接口的方法
参数。该方式要求在映射配置文件的 SQL 中使用 #{ 内容 } 时,
里面的内容必须和 map 集合中键的名称一致。
4.6.1 编写接口方法
public interface EmployeeMapper {
//修改一条数据
public Integer updateEmp(Map<String,Object>
map);
}
4.6.2 编写SQL语句
<!--通过key获取value的值-->
<update id="updateEmp" parameterType="Employee">
update t_emp set emp_name = #
{empName},emp_salary = #{empSalary} where
emp_id = #{empId}
</update>
4.6.3 编写测试代码
@Test
public void testUpdate(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
Map<String,Object> map=new HashMap<>();
map.put("empId",3);
map.put("empName","ww");
map.put("empSalary",55.33);
Integer row = employeeMapper.updateEmp(map);
//输出结果
System.out.println(row);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}

.数据输出

5.1 输出概述

数据输出总体上有两种形式:
  • 增删改操作返回受影响行数:直接在接口方法中使用 int
    long 类型接收即可
  • 查询操作的查询结果
我们需要做的是,指定查询的输出数据类型即可!
并且插入场景下,实现主键数据回显示!
resultType = " 全限定符 | 别名 | 如果是返回集合类型,写
范型类型即可

5.2 返回单个简单类型

5.2.1 编写接口方法
public interface EmployeeMapper {
//查询总条数
public Integer findTotalCount();
}
5.2.2 编写SQL语句
<select id="findTotalCount" resultType="int">
select count(*) from t_emp
</select>
 5.2.3 编写测试代码
@Test
public void testDemo(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
Integer totalCount =
employeeMapper.findTotalCount();
//输出结果
System.out.println(totalCount);
//释放资源
sqlSession.close();
}

5.3 返回实体类对象

5.3.1 编写接口方法
public interface EmployeeMapper {
//根据ID查询用户信息
public Employee findEmpById(Integer empId);
}
5.3.2 编写SQL语句
<select id="findEmpById" parameterType="int"
resultType="Employee">
select * from t_emp where emp_id = #{empId}
</select>
5.3.3 编写测试代码
@Test
public void testDemo(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
Employee employee =
employeeMapper.findEmpById(1);
//输出结果
System.out.println(employee);
//释放资源
sqlSession.close();
}

5.4 返回List类型

查询结果返回多个实体类对象,希望把多个实体类对象放在
List 集合中返回。此时不需要任何特殊处理,在 resultType
性中还是设置实体类类型即可。
5.4.1 编写接口方法
public interface EmployeeMapper {
//查询所有数据
public List<Employee> findAll();
}
5.4.2 编写 SQL 语句
<select id="findAll" resultType="Employee">
select * from t_emp
</select>
5.4.3 编写测试代码
@Test
public void testDemo(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
List<Employee> employeeList =
employeeMapper.findAll();
//输出结果
for (Employee employee : employeeList) {
System.out.println(employee);
}
//释放资源
sqlSession.close();
}

5.5 返回Map类型

适用于 SQL 查询返回的各个字段综合起来并不和任何一个现有
的实体类对应,没法封装到实体类对象中。
5.5.1 编写接口方法
public interface EmployeeMapper {
//查询所有员工的最高工资,最低工资,平均工资
public Map<String,Object> findSalary();
}
5.5.2 编写SQL语句
<select id="findSalary" resultType="Map">
select max(emp_salary) 最高工资,min(emp_salary) 最低工资,avg(emp_salary) 平局工资 from t_emp
</select>
5.5.3 编写测试代码
@Test
public void testDemo(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
Map<String, Object> map =
employeeMapper.findSalary();
//输出结果
Set<Map.Entry<String, Object>> entrySet =
map.entrySet();
for (Map.Entry<String, Object> entry :
entrySet) {
System.out.println(entry.getKey()+"..."+entry.g
etValue());
}
//释放资源
sqlSession.close();
}

5.6 主键回填

5.6.1 自增长类型主键

public interface EmployeeMapper {
//添加数据
public Integer insertEmp(Employee employee);
}
<!--
主键回填:当Mybatis执行新增后,会将数据库中该
条数据新增后的主键回填到实体的属性上
useGeneratedKeys:是否启用主键回填
keyProperty:指定主键回填到实体的哪个属性上
keyColumn:指定数据库中哪一列是主键(可选)
-->
<insert id="insertEmp" parameterType="Employee"
useGeneratedKeys="true" keyProperty="empId">
insert into t_emp values(null,#{empName},#
{empSalary})
</insert>
@Test
public void testDemo(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
EmployeeMapper employeeMapper =
sqlSession.getMapper(EmployeeMapper.class);
//通过多态调用方法
Employee employee=new Employee(null,"赵
六",11.22);
Integer integer =
employeeMapper.insertEmp(employee);
//输出结果
System.out.println(integer);
//后续需要完善员工信息
System.out.println(employee);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
5.6.2 非自增长类型主键
而对于不支持自增型主键的数据库或者字符串类型主键,则可
以使用 selectKey 子元素: selectKey 元素将会首先运行, id
会被设置,然后插入语句会被调用!
使用 selectKey 帮助插入 UUID 作为字符串类型主键示例:
CREATE TABLE t_user (
id varchar(64) primary key,
username varchar(50),
password varchar(50)
)
public interface UserMapper {
//添加数据
public Integer insertUser(User user);
}
<mapper namespace="com.lzw.mapper.UserMapper">
<insert id="insertUser"
parameterType="user">
<!--
keyProperty:设置为实体的哪个属性,
resultType:设置返回值类型,
order:值为after和before
after: sql之后执行,before: sql之前执行
-->
<selectKey order="BEFORE"
resultType="string" keyProperty="id">
select replace(UUID(),'-','')
</selectKey>
insert into t_user values(#{id},#
{username},#{password})
</insert>
</mapper>
@Test
public void testDemo(){
//使用工具类获取SqlSession对象
SqlSession sqlSession =
SqlSessionUtil.openSession();
//基于接口获取实现类对象(代理对象)
UserMapper userMapper =
sqlSession.getMapper(UserMapper.class);
//通过多态调用方法
//String id=
UUID.randomUUID().toString().replace("-","");
User user=new User(null,"zs","123456");
Integer integer =
userMapper.insertUser(user);
//输出结果
System.out.println(integer);
//后续需要完善用户信息
System.out.println(user);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}

see you later!!!


原文地址:https://blog.csdn.net/2201_75555400/article/details/142961862

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!