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(数据源)
- environment(环境变量)
- 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>
四.数据输入
- 简单类型:只包含一个值的数据类型
- 基本数据类型:int、byte、short、double、……
- 基本数据类型的包装类型:Integer、Character、Double、……
- 字符串类型:String
- 复杂类型:包含多个值的数据类型
- 实体类类型:Employee、Department、……
- 集合类型:List、Set、Map、……
- 数组类型: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)!