提示:写代码要严谨
文章目录
前言
提示:
mybatis官网
MyBatis 代码最主要的是简化 dao 层代码,把dao中复杂的、大量的JDBC代码,简化成了接口和映射文件
ORM思想
O:po类
R:关系,数据库
M:mapper,映射
前期准备
第一步:新建项目Maven项目
在下一步中勾选第一个选项,创建一个简单的项目,最后填写相关信息后完成
如果有需要导入的配置文件:
这样做的好处是:即便原有的配置文件被删掉也没事
第二步:完善 pom.xml 文件
项目建成后在 pom.xml 文件中导入相关代码,比如:
缺什么加什么
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 使用log4j输出更多的日志信息 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<!--表示需要编译的源文件路径-->
<directory>src/main/java</directory>
<includes>
<!--表示以.properties和*.xml结尾的文件将进行编译-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<!--表示需要编译的源文件路径-->
<directory>src/main/resources</directory>
<includes>
<!--表示以.properties和*.xml和.yml结尾的文件将进行编译-->
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.yml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
第三步:配置 main/resources 文件夹
mybatis-config.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>
<typeAliases>
<package name=""/>
</typeAliases>
<!-- 配置数据源相关属性 -->
<environments default="development">
<!-- 可以配置多个数据源环境,默认使用default中的值 -->
<environment id="development">
<!-- 使用jdbc的事务管理 -->
<transactionManager type="MANAGED" />
<!-- 配置数据源,并使用自带数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8&serverTimezone=Asia/Shanghai" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- 配置映射文件,可配置多个 -->
<mappers>
<!-- 指定映射文件路径,复制一下 -->
<mapper resource="" />
<mapper resource="" />
</mappers>
</configuration>
log4j.properties
配置文件,可以显示 log 输出
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{
yyyy-MM-dd HH:mm:ss} %m%n
log4j.rootLogger=debug,stdout
- 新建映射文件
XyzMapper.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="">
</mapper>
第四步:在 test/java 文件夹下创建 test 测试类
import java.io.InputStream;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class AppTest {
private SqlSession session=null;
@Before
public void before() throws Exception {
// 与main/resources文件夹中的 mybatis-config.xml 配置文件名字对应
InputStream input = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(input);
session= ssf.openSession();
}
@After
public void after() {
session.close();
}
@Test
public void test() {
}
}
提示:以下是本篇文章正文内容,下面案例可供参考
MyBatis CRUD操作流程
MySQL建表语句:
drop table if exists emp;
create table EMP
(
EMPNO int primary key,
ENAME varchar(20),
JOB varchar(9),
MGR int,
HIREDATE date,
SAL double,
COMM double,
DEPTNO int,
foreign key (DEPTNO) references DEPT (DEPTNO)
);
增加功能
在main/java文件夹中新建 po 包及类
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private Date hiredate;
private Double sal;
private Double comm;
private Integer Deptno;
// 自动生成 Getter、Setter、toString()、有参无参方法
}
在main.resources文件夹中新建映射文件 mapper.xml
这里面写的就是SQL语句
parameterType里面的参数是:在 po 类中双击类的名字,右键复制限定名
SQL语句中的具体数据要写成#{}
占位符的写法
大括号中的属性名要与 po 类中的名字一致(注意大小写),而 po 类中的名字要与数据库中的名字一致
<mapper namespace="emp">
<!-- 方法名, 参数 返回值(只有查询有) -->
<insert id="insertEmp" parameterType="com.mybatis.po.Emp">
insert into emp
values(#{empno},#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{Deptno})
</insert>
</mapper>
接下来在 config.xml 文件中增加配置文件
<!-- 配置映射文件,可配置多个 -->
<mappers>
<!-- 指定映射文件路径,复制一下 -->
<mapper resource="EmpMapper.xml" />
</mappers>
接下来就可以测试了,测试代码:
@Test
// insertEmp()起个名
public void insertEmp() {
Emp emp = new Emp(8988, "张三", "Java", 7790, new Date(2023, 10, 23), 10000.0, 99.0, 20);
// "emp.insertEmp" → "namespace的值.insertEmp方法名是映射文件中的id"
int i = session.insert("emp.insertEmp", emp);
System.out.println(i);
}
接下来右键该 test 类测试,点击运行方式 → JUnit测试
他会运行前面带@Test
的方法
删除功能
#{}
占位符中的名字 如果参数是 po 类型,那么名字必须是属性名,如果参数是基本类型或String,那么参数名字自定义
映射文件代码:
<delete id="deleteEmp" parameterType="int">
delete from emp
where empno = #{
随便起名}
</delete>
测试类代码:
@Test
public void deleteEmp() {
int i = session.delete("emp.deleteEmp",8966);
System.out.println(i);
}
修改功能
映射文件代码:
<update id="updateEmp" parameterType="com.mybatis.po.Emp">
update emp
set ename=#{
ename},job=#{
job},mgr=#{
mgr},hiredate=#{
hiredate},sal=#{
sal},comm=#{
comm},Deptno=#{
Deptno}
where empno = #{
empno}
</update>
测试类代码:
@Test
public void updateEmp() {
Emp emp = new Emp(8988,"enen","java全栈",7790,new Date(2003, 10, 13), 11000.0, 999.0, 20);
int i = session.update("emp.updateEmp",emp);
System.out.println(i);
}
查询功能
#{} 占位符
映射文件代码:
<select id="queryEmps" parameterType="String" resultType="com.mybatis.po.Emp">
select * from emp
where ename like concat('%',#{名字模糊查询},'%')
</select>
测试类代码:
@Test
public void queryEmp() {
List<Emp> list = session.selectList("emp.queryEmps","T");
for (Emp emp : list) {
System.out.println(emp);
}
}
除了#{}
外还有种占位符叫${}
,现在用的比较少
${} 占位符
映射文件代码:
<select id="queryEmps" parameterType="String" resultType="com.mybatis.po.Emp">
select * from emp
where ename like concat('%','${value}','%')
</select>
测试类代码:
@Test
public void queryEmps() {
// 查询部门名字中带 O 的
List<Emp> list = session.selectList("emp.queryEmps","O");
for (Emp emp : list) {
System.out.println(emp);
}
}
两种占位符的区别❗
${}
使用的是普通的 Statement 语句运行,运行效率低,采用的是SQL语句拼接的方式,可能发生SQL注入安全问题
#{}
使用的是 PreparedStatement 预编译语句,运行效率高,能够防止SQL注入,安全性高
映射文件总结❗
- 映射文件可以理解为dao类,里面写的就是SQL语句
- 映射文件中的
insert update delete select
标记,理解为dao类中的方法 id
属性理解为方法名,parameterType
属性理解为参数,resultType
属性理解为方法返回值(增删改不需要配置,因为只能是 int 类型)- SQL语句中的具体数据要写成
#{}
占位符的写法,#{属性名1},#{属性名2}
#{}
占位符中的名字 如果参数是 po 类型,那么名字必须是属性名,如果参数是基本类型或字符串,那么参数名字自定义alt + /
是提示
mapper 代理方式实现CRUD
mapper代理开发规范
1.在同一个包中新建一个接口和与之同名的映射文件
2.映射文件的namespace必须是接口的限定名
3.映射文件中语句id必须和接口中方法名一致
4.映射文件中语句parameterType必须和接口中方法参数一致
5.映射文件中语句resultType必须和接口中方法返回值类型一致
一个 mapper.xml 对应一个 mapper.java 接口,接口的实现类由MyBatis 自动生成
在数据库中新建客户表
drop table if exists cust;
CREATE TABLE cust (
id INT PRIMARY KEY auto_increment, # id自增
name VARCHAR(50) NOT NULL, # 姓名
phone VARCHAR(20), # 电话
birthday DATE, # 出生日期
balance DOUBLE # 余额
);
INSERT INTO cust (id, name, phone, birthday, balance) VALUES (1, '张三', '13611111111', '1990-01-01', 1000.00);
INSERT INTO cust (id, name, phone, birthday, balance) VALUES (2, '李四', '13722222222', '1995-02-02', 2000.00);
INSERT INTO cust (id, name, phone, birthday, balance) VALUES (3, '王五', '13833333333', '1985-03-03', 3000.00);
main/java内新建 po 包及其Java类
public class Cust {
private Integer id;
private String name;
private String phone;
private Date birthday;
private double balance;
// 自动生成 Getter、Setter、toString()、有参无参方法
}
接着在main/java内新建Cust 接口及 .xml
文件
在CustMapper.xml 文件中,namespace
是接口的限定名
<mapper namespace="com.mybatis.mapper.CustMapper">
在mybatis-config.xml文件中的配置:
<!-- 1.package name是po包的限定名 -->
<typeAliases>
<package name="com.mybatis.po"/>
</typeAliases>
<!-- 中间代码省略 -->
<!-- 2.配置映射文件,可配置多个 -->
<mappers>
<!-- 指定映射文件包(mapper包) 的限定名,复制一下 -->
<package name="com.mybatis.mapper"/>
</mappers>
增加功能
首先在接口中定义方法:
int insertCust(Cust cust);
Customers.xml 文件代码:
<insert id="insertCust" parameterType="Cust">
insert into cust(id,name,phone,birthday,balance)
values (#{id},#{name},#{phone},#{birthday},#{balance})
</insert>
测试代码:
@Test
public void insertCust() {
// 得到mapper接口实现类对象
CustMapper mapper = session.getMapper(CustMapper.class);
// 主键是自增的,所以id可以为空
Cust cust = new Cust(null,"张三", "15794612345", new Date(2003-8-03),20.5);
// 调用接口中定义的方法
int i = mapper.insertCust(cust);
System.out.println(i);
}
增加后怎么拿到主键呢?
在映射文件中:加上查询主键值
<insert id="insertCust" parameterType="Cust">
<!-- 获得自动递增的主键值 -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
<!--
查一个虚表,最后一次插入的值
先执行增加的sql语句,再执行查询,获取插入的主键值,然后赋值给keyProperty的id
-->
select last_insert_id() from dual
</selectKey>
insert into cust(id,name,phone,birthday,balance)
values (#{
id},#{
name},#{
phone},#{
birthday},#{
balance})
</insert>
测试代码加上:
System.out.println("增加的主键值是:"+cust.getId());
删除功能
首先在接口中定义方法:
int deleteCust(int id);
映射文件 CustMapper.xml 中:
<delete id="deleteCust" parameterType="int">
delete from cust
where id = #{
int类型随便起名}
</delete>
测试代码:
@Test
public void deleteCustomers() {
CustMapper mapper = session.getMapper(CustMapper.class);
int i = mapper.deleteCust(3);
System.out.println(i);
}
修改功能
首先在接口中定义方法:
int updateCust(Cust cust);
映射文件 CustMapper.xml 中:
<update id="updateCust" parameterType="Cust">
update cust
set name = #{name}, phone = #{phone}, birthday = #{birthday}, balance = #{balance}
where id = #{id}
</update>
测试代码:
@Test
public void updateCust() {
CustMapper mapper = session.getMapper(CustMapper.class);
Cust cust = new Cust(5,"李四", "15846012345", new Date(2013-8-03),1320.5);
int i = mapper.updateCust(cust);
System.out.println(i);
}
查询功能
首先在接口中定义方法:
// id查询
Cust queryCustById(int id);
// 名字和电话的模糊查询
List<Cust> queryCusts(Cust cust);
映射文件 CustMapper.xml 中:
<select id="queryCustById" parameterType="int" resultType="Cust">
select * from cust
where id = #{
随便起名}
</select>
<select id="queryCusts" parameterType="Cust" resultType="Cust">
select * from cust
where name like concat('%',#{
name},'%')
and phone like concat('%',#{
phone},'%')
</select>
测试代码:
@Test
public void query() {
CustMapper mapper = session.getMapper(CustMapper.class);
mapper.queryCustById(6);
Cust cust = new Cust(null,"四", "2345", null,130020.5);
mapper.queryCusts(cust);
}
重点看控制台输出语句是否正确