MyBatis
文章目录
前言
为什么要学MyBatis?
- 帮助程序员将数据存入到数据库中
- 传统的JDBC代码太复杂,为了简化它,创建了这么一个框架,实现了自动化
- 方便使用
- 最重要的一点:使用的人多
优点:
- 灵活
- 简单易学
- 解除sql与程序代码的耦合
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql
一、MyBatis是什么?
- MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
- MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
什么是持久化
数据持久化
持久化就是将程序的数据在持久状态和瞬时状态转化的过程
数据库(JDBC)和IO文件持久化,可以持久化数据
为什么要持久化?
- 因为内存有一个断电即失的特性,有一些信息对象不能丢失
- 内存太贵
什么是持久层
Java学习中,有很多层,Dao层、Service层、Controller层~~
持久层就是完成持久化工作的代码块
二、学习MyBatis所需资源
1.下载MyBatis
MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。
查询可知在Github官网(https://github.com)即可获取
在这里下载压缩包就行
2.获取Maven中要使用的MyBatis的Jar包
在Maven仓库(https://mvnrepository.com)里直接搜索MyBatis
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
3.官方文档
学习的东西都是参照官方文档
MyBatis中文文档:https://mybatis.org/mybatis-3/zh/index.html
三、第一个MyBatis程序
这里可以看一下我们的MyBatis的官方文档入门我们的学习大部分资源是官方给的
我们的项目目录大概是这样:
这里,我来为大家演示官方给的配置如何使用
1.自己创建数据库
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user`(`id`,`name`,`pwd`) values (1,'上泽','200126'),(2,'狂神','20020128'),(3,'南迁','5212415');
建议手动敲一遍,加深印象
2.演示
我们需要的实体类文件
User类
package com.ze.pojo;
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
创建一个普通的Maven项目,我们需要的jar包有mysql的配置文件、junit、Mybatis
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
文档中的第二步
我们会有很多改动
mybatis-coinfig.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="200126"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/ze/dao/UserMapper.xml"/>
</mappers>
</configuration>
MybatisUtils
package com.ze.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 MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession连接
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
文档第三步
这一步是获取SqlSession,SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。也就是说我们可以拿到我们所需要的数据,直接写入测试类,这里我们只使用了一种方法,也就是第二种,另一种是官方不推荐的,这种好处是 代码不仅更清晰,更加类型安全,还不用担心可能出错的字符串字面值以及强制类型转换
UserDaoTest
package com.ze.dao;
import com.ze.pojo.User;
import com.ze.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
}
我们的测试文件都是官方推荐使用的方法
给一个xml映射
下面的调用方法也是推荐第二种
第二种方法有很多优势,首先它不依赖于字符串字面值,会更安全一点;其次,如果你的 IDE 有代码补全功能,那么代码补全可以帮你快速选择到映射好的 SQL 语句。
UserMapper.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="com.ze.dao.UserDao">
<select id="getUserList" resultType="com.ze.pojo.User">
select * from user
</select>
</mapper>
这里的namespace是接口路径 id为接口方法名称 resultType为实体类路径
接口UserDao
package com.ze.dao;
import com.ze.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getUserList();
}
最后使用测试类,可测出结果
运行时查看xml文件是否加载出来了
因为Maven的约定大于配置,所以可能有配置文件无法导出的问题,解决方案是在配置文件pom.xml中加入如下配置
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
最后运行时可能有很多离谱的问题,我就碰到了一个Causedby:org.apache.ibatis.exceptions.PersistenceException
看了好久是因为在xml文件中加了注释报错的,只觉离谱。有同样问题的小伙伴直接删除即可,或者去看一下这个人的博客看看其他解决办法
当然,第一次运行可能还有其他的错误,网上基本都有解决的方法,我不在一 一阐述
3.以上总结
我们配置好以后,增删改查只有接口方法,=sql语句,和使用不同
在接口中添加方法可以一个一个玩
package com.ze.dao;
import com.ze.pojo.User;
import java.util.List;
public interface UserDao {
//查询所有用户
List<User> getUserList();
// 查询指定id
List<User> getUserId(int id);
// 添加操作
int insertUser(User user);
// 删除指定用户
int deleteUser(int id);
// 修改信息
int updateUser(User user);
}
加入sql语句
<?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="com.ze.dao.UserDao">
<select id="getUserList" resultType="com.ze.pojo.User">
select * from user
</select>
<select id="getUserId" resultType="com.ze.pojo.User" parameterType="int">
select * from user where #{id};
</select>
<insert id="insertUser" parameterType="com.ze.pojo.User" >
insert into user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>
<update id="updateUser" parameterType="com.ze.pojo.User">
update user set name=#{name},pwd=#{pwd} where id=#{id} ;
</update>
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id};
</delete>
</mapper>
测试类中测试
@Test
public void test2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserId(1);
System.out.println(userList);
sqlSession.close();
}
@Test
public void test3(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int insert = mapper.insertUser(new User(4, "23", "1234"));
sqlSession.commit();
sqlSession.close();
}
//删除
@Test
public void test4(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.deleteUser(4);
sqlSession.commit();
sqlSession.close();
}
@Test
public void test5(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.updateUser(new User(4,"不糊","456"));
sqlSession.commit();
sqlSession.close();
}
注意:
- 增加inster、删除delete和修改update需要提交事务
**sqlSession.commit();**否则不会更新数据。 - **sql语句后面的“;”加不加:**针对mysql来说,在mybatis的xml文件中两种形式都是支持的。而对于Oracle,加分号的写法会报“ora-00911:无效字符”的异常。 具体的原因是 “Oracle数据库接口对书写格式要求非常严格,有时候即使多加一个空格,多加一个逗号,分号,回车等都不行”。
- #{xx}容易写错为{#xx},这个是我的问题
4.万能的Map
在上面我们使用到User实体类,在编写sql语句时需要所有的属性id,name,pwd
update user set name=#{name},pwd=#{pwd} where id=#{id} ;
如果User类有很多的属性(想象为100个),而我们只是想修改密码,这样就会非常繁琐,而Map就能给我们解决这样的问题
给大家简单的示范一下,这个思想以后的开发中经常会使用
添加方法
int updateUser2(Map<String,Object> map);
xml
<update id="updateUser2" parameterType="map">
update user set pwd=#{password} where id=#{Id}
</update>
这里的不同需要注意一下,参数类型parameter为map ,Id与password自己命名,与Map的key值等同(下面自己添加值),我们取得的就是value
测试
@Test
public void map1Test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("Id",2);
map.put("password","5555");
mapper.updateUser2(map);
sqlSession.commit();
sqlSession.close();
}
注:
- 对象传递参数,在sql中取对象的属性 parameterType="Object"
- 只有一个一个参数的情况下,可以直接在sql中取到(parameterType="Object"可以省略)
- Map传递参数,在sql中取用key即可 parameterType="map"
5.模糊查询
模糊查询怎么写?
- java代码执行的时候,传递通配符% %
List<User> inShang(String name);
<select id="inShang" resultType="com.ze.pojo.User">
select * from user where `name` like #{name};
</select>
@Test
public void testIn(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> user = mapper.inShang("%上%");
for (User user1 : user) {
System.out.println(user1);
}
sqlSession.close();
}
这种方式比较安全,但是大多数人不会这样写
2. 在sql拼接中使用通配符
<select id="inShang" resultType="com.ze.pojo.User">
select * from user where `name` like "%"#{name}"%";
</select>
List<User> user = mapper.inShang("上");
这种情况存在sql注入
运行结果: