目录
一、MyBatis概述
1、1 框架
java常用的框架有SSM、SpringBoot、SpringCloud等。
其中,MyBatis属于SSM框架之一,MyBatis是对JDBC进行封装后的简化框架
学习MyBatis之前,需要先学习JDBC。
对SSM三大框架建议学习顺序:
MyBatis、Spring、SpringMVC
Spring、Mybatis、SpringMVC
1、2 MyBatis与JDBC
MyBatis是对JDBC进行封装后的简化框架,底层还是会执行JDBC代码,只是程序员使用MyBatis对数据库进行CRUD(CRUD:增删改查)等操作,不需要像JDBC一样写太繁琐的代码,提高了开发效率。
JDBC代码:
//sql语句写死在java程序中
String sql = "insert into t_user(id,user_name,user_pwd) values(?,?,?)"
PreparedStatement ps = con.prepareStatement(sql);
//以下代码太过繁琐
ps.setString(1,"1");
ps.setString(2,"张三");
ps.setString(3,"123");
//这里只是传3个值,如果是10多个呢,是不是要多写几个ps.setString方法
int count = ps.executeUpdate();
MyBatis有XML开发、注解开发。在官方解释中,对于复杂的SQL语句,如果使用注解开发,会让你的SQL语句更加混乱,因此,如果是简单的CRUD操作可以使用注解开发,如果是要做一些复杂的操作,最好使用XML来映射。
1、3 三层架构
学习MyBatis之前,应该知道什么是MVC三层架构。MyBatis是属于三层架构中的数据持久层。
MVC三层架构图:
作者建议: 学习完Spring、SpringMVC之后,可以尝试自己做一个基于SSM的Web项目。因为后期SSM整合之后,堪称“地狱配置”,很多小伙伴学习到SpringMVC,会把前面Spring、MyBatis遗忘,使用SSM做一个项目,可以巩固一下知识,后期学习SpringBoot就不需要担心那么多配置。
二、MyBatis第一个入门程序
学习MyBatis之前,最好先去学习一下Maven(你就不用手动下载依赖了)
话不多说,直接上号!!!
先准备好一张数据库表t_user,这里的id是主键自增
1、创建一个Maven项目,这里使用JDK17(或者JDK8)
2、 创建完Maven项目后,在pom.xml文件中添加依赖(不要看见这么多字就被劝退,这只是一些jar包,帮助你开发的),添加完依赖后记得给Maven刷新一下 ps:如果第一次引入依赖,会出现红字,刷新一下Maven就可以了
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
在resourece目录下创建一个xml文件,命名为mybatis-config.xml(命名无所谓)
在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>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="t_user.xml"/>
</mappers>
</configuration>
3、在resources创建SQL映射XML文件,命名t_user.xml
在映射文件中,写入sql语句(这里的namespace先随便写)
sql映射文件记得写到核心配置文件中!!(<mappers>标签中)
<?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="abc">
<select id="select" resultType="pojo.User">
select id,user_name userName,user_pwd userPwd from t_user where id=#{id}
</select>
</mapper>
编写java程序
1、创建pojo类
package pojo;
public class User {
private Integer id;
private String userName;
private String userPwd;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", userPwd='" + userPwd + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public User(Integer id, String userName, String userPwd) {
this.id = id;
this.userName = userName;
this.userPwd = userPwd;
}
public User() {
}
}
2、查询数据
public class mybatis {
@Test
public void test1(){
try {
//SqlSessionFactoryBuilder的作用就是创建SqlSessionFactory
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//SqlSessionFactory对应一个数据库
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
//pojo类已经实现toString,可以不用转成User类
//这里是"select"要跟sql映射文件中的<select>标签的id保持一致
Object user = sqlSession.selectOne("select", 1);
//将映射结果输出
System.out.println(user);
} catch (IOException e) {
e.printStackTrace();
}
}
}
3、查询结果
三、使用MyBatis完成CRUD操作
第一个入门程序很简单吧,接下来把CRUD操作也做一遍吧。
加油,未来的java高级开发工程师.
(1)向数据表进行insert操作
在sql映射文件中编写sql语句
(注意这里id是null,因为是主键自增,它会自动给id赋值)
<?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="abc"> <insert id="insert"> insert into t_user(id,user_name,user_pwd) values(null,"赵六","10086") </insert> </mapper>
编写java程序
public class mybatis { @Test public void insert(){ try { SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); SqlSession sqlSession = sqlSessionFactory.openSession(); //这里是"insert"要跟sql映射文件中的<insert>标签的id保持一致 int count = sqlSession.insert("insert"); sqlSession.commit();//手动提交事物 System.out.println("插入"+count+"条数据"); } catch (IOException e) { e.printStackTrace(); } } }
执行结果
(2)向数据表进行update操作
在sql映射文件中编写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="abc"> <update id="update"> update t_user set user_name="java高级开发工程师",user_pwd="root" where user_name="张三" </update> </mapper>
编写Java程序
public class mybatis { @Test public void update(){ SqlSessionFactory sqlSessionFactory = null; try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); SqlSession sqlSession = sqlSessionFactory.openSession(); //这里是"update"要跟sql映射文件中的<update>标签的id保持一致 int count = sqlSession.update("update"); sqlSession.commit();//手动提交事物 System.out.println("更新了"+count+"条数据"); } catch (IOException e) { e.printStackTrace(); } } }
执行结果
(3)向数据表进行delete操作
在sql映射文件中编写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="abc"> <delete id="delete"> delete from t_user where user_name="李四" </delete> </mapper>
编写java程序
public class mybatis { @Test public void delete(){ try { SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); SqlSession sqlSession = sqlSessionFactory.openSession(); //这里是"delete"要跟sql映射文件中的<delete>标签的id保持一致 int count = sqlSession.delete("delete"); sqlSession.commit();//手动提交事物 System.out.println("删除"+count+"条数据"); } catch (IOException e) { e.printStackTrace(); } } }
执行结果
“李四”的数据被删除了
(4)向数据库进行select操作
这里不再演示只查一条记录,只查一条记录在入门程序已经展示过了。
查所有记录,<select>标签需要给resultType属性赋值,告诉mybatis你要映射的实体类是什么(带包名),也可以用map集合映射等等。
在sql映射文件中编写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="abc"> <select id="selectAll" resultType="pojo.User"> select id,user_name userName,user_pwd userPwd from t_user </select> </mapper>
编写java程序
public class mybatis { @Test public void selectAll(){ try { SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); SqlSession sqlSession = sqlSessionFactory.openSession(); //这里是"selectAll"要跟sql映射文件中的<selectAll>标签的id保持一致 List<User> users = sqlSession.selectList("selectAll"); //以下是jdk8的新特性,将集合内容输出 users.forEach(user -> System.out.println(user)); } catch (IOException e) { e.printStackTrace(); } } }
执行结果
四、MyBatis核心配置文件
(1)properties
<properties/>标签有两个属性:resource、url,其中最常用的是resource属性
resource标签
(1)在类的根目录下创建一个properties文件
(2)将以下内容复制到properties文件中
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456
(3)在mybatis核心配置文件中配置properties标签的resource属性
<properties resource="jdbc.properties"/>
(4)在mybatis核心配置文件中配置environment标签
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
(5)运行程序
分析: 如果数据库登录信息被修改,不需要修改代码,只需要将properties文件中的配置信息更新即可,假如你写好一个项目交给客户,客户又不懂代码,那你只需要告诉他将数据库的账号密码写入properties文件中,不过一般不这么做,因为客户可能在更新账号密码的时候将jdbc.xxx=删除,但是他又不懂代码,这时就出现报错了。这里只是告诉你properties的用法。
url标签(不建议使用)
url的用法跟resource的用法差不多,只是url用的是绝对路径,你可以把properties文件放到你想放的地方,但不建议这么做,因为这样会降低程序的移植性,如果存放到类的根目录下,那你整个项目移动到别的设备,路径也不会报错。
使用url只需要修改以下地方,将properties文件放到你想放的位置,我这里放到电脑D盘的位置
<properties url="file:///d:/jdbc.properties"/>
执行程序
注意这里的file:后面加的是三条反斜杠,再加路径
(2)transactionManager
transactionManager标签有一个type属性,该属性有两个值:JDBC、MANAGED。
当type属性为JDBC
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
MyBatis会采用原生的JDBC事物管理,底层还是会调用JDBC的事物。
开启事物:con.setAutoCommit(false);
提交事物:con.commit();
当type属性为MANAGED
<environments default="dev">
<environment id="dev">
<transactionManager type="MANAGED"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
MyBatis会放弃原生的JDBC事物管理,把事物交给其他容器去管理,如spring。
如果没有其他容器,则每执行一条DML语句,就提交一次事物。
(3)datasource
datasource标签的type属性的值有:UNPOOLED、POOLED、JNDI
UNPOOLED:不会使用连接池,即每次都会创建一个新的jdbc对象
POOLED:使用连接池,这个连接池是mybatis实现的数据库连接池
POOLED的其他属性:
poolMaximumActiveConnections:最⼤的活动的连接数量。默认值10
poolMaximumIdleConnections:最⼤的空闲连接数量。默认值5
poolMaximumCheckoutTime:强⾏回归池的时间。默认值20秒。
poolTimeToWait:当⽆法获取到空闲连接时,每隔20秒打印⼀次⽇志
JNDI:表示对接JNDI服务器中的连接池,简单说就是第三方连接池。如dbcp、c3p0、druid(德鲁伊)等,就需要采用这种方式。
(4)properties
properties不仅可以引入外部文件,还可以这样写,同样也是用¥{}引用。
<properties resource="jdbc.properties">
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="123456"/>
</properties>
(5)mapper
mapper标签是用来指定SQL映射文件的路径。
resource:从类路径中加载url:从指定的全限定资源路径中加载class:使⽤映射器接⼝实现类的完全限定类名package:将包内的映射器接⼝实现全部注册为映射器
resource
这种方式加载SQL映射文件,需要将文件放到resources目录下或者子目录
<mappers>
<mapper resource="t_user.xml"/>
</mappers>
url
同样也是用绝对路径,将SQL映射文件放到你想放的地方,再用绝对路径进行引用,当然这种方法也不建议,这样会导致程序的移植性差。
<mappers>
<mapper url="file:///D:/t_user.xml"/>
</mappers>
class和package在文章第七点下面讲解。
五、在WEB中应用MyBatis(使用MVC架构模式)
(1)创建一个新的module
(2)在webapp创建index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我的第一个web项目-mybatis</title>
</head>
<script type="text/javascript">
window.onload=function () {
document.getElementById("btn").onclick=function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange=function () {
if (xhr.readyState==4) {
if (xhr.status>=200&&xhr.status<300) {
document.getElementById("myspan").innerHTML=xhr.responseText
}
}
}
var username = document.getElementById("username").value;
xhr.open("GET","/web/first?username="+username,true)
xhr.send()
}
}
</script>
<body>
<h2>查询密码</h2>
请输入要查询的用户:<input type="text" id="username"><br>
<input type="button" id="btn" value="提交">
密码:<span id="myspan"></span>
</body>
</html>
(3)创建mybatis核心配置文件和SQL映射文件
核心配置文件
<?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="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="User.xml"/>
</mappers>
</configuration>
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="user">
<select id="selectUserPwd" resultType="com.pojo.User">
select user_name username,user_pwd password from t_user where user_name=#{username}
</select>
</mapper>
(4)搭建控制层和持久层
controller类
package com.controller;
import com.service.UserService;
import com.service.impl.UserServiceImpl;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/first")
public class controller extends HttpServlet {
UserService userService = new UserServiceImpl();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
//获取用户名字
String username = request.getParameter("username");
String pwd = userService.selectUserPwd(username);
out.print(pwd);
}
}
service接口以及实现类
package com.service;
public interface UserService {
//查询用户密码
String selectUserPwd(String username);
}
package com.service.impl;
import com.mapper.UserMapper;
import com.mapper.impl.UserMapperImpl;
import com.service.UserService;
public class UserServiceImpl implements UserService {
UserMapper userMapper = new UserMapperImpl();
@Override
public String selectUserPwd(String username) {
return userMapper.selectPwd(username);
}
}
mapper接口以及实现类
package com.mapper;
public interface UserMapper {
//查询密码
String selectPwd(String username);
}
package com.mapper.impl;
import com.mapper.UserMapper;
import com.pojo.User;
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;
public class UserMapperImpl implements UserMapper {
@Override
public String selectPwd(String username) {
User user = null;
try {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
user=sqlSession.selectOne("selectUserPwd",username);
} catch (IOException e) {
e.printStackTrace();
}
return user.getPassword();
}
}
pojo类
package com.pojo;
public class User {
String username;
String password;
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
}
(5)搭建tomcat
路径设置为/web,然后点apply
点击server
启动tomcat,点击这只小虫子(debug)
六、MyBatis中使用接口代理getMapper
在mybatis中,有一个方法可以动态的生成mapper接口的实现类,程序员只需要写出mapper接口,SQL映射文件即可,mapper接口的实现类可以让mybatis动态生成。
(1)将mapper实现类删掉
(2)更新Service实现类
package com.service.impl;
import com.mapper.UserMapper;
import com.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
public class UserServiceImpl implements UserService {
@Override
public String selectUserPwd(String username) {
SqlSession sqlSession = null;
try {
//可以将Sqlsession封装成工具类,就不会像下面这么复杂
sqlSession = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession();
} catch (IOException e) {
e.printStackTrace();
}
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
return userMapper.selectPwd(username);
}
}
(3)更新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.mapper.UserMapper">
<select id="selectPwd" resultType="String">
select user_pwd password from t_user where user_name=#{username}
</select>
</mapper>
这里的namespace需要写接口的全限定命,select标签的id需要写方法的名字
解释:getmapper()方法底层是采用反射机制
七、MyBatis小技巧
(1)#{}和${}
在以上SQL映射文件中,给参数传值都是采用#{}符号,还有一种是${}。
#{}:先编译sql语句,再给占位符传值,底层是PreparedStatement实现。可以防⽌sql注⼊,⽐较常⽤。
${}:先进⾏sql语句拼接,然后再编译sql语句,底层是Statement实现。存在sql注⼊现象。只有在需要 进⾏sql语句关键字拼接的情况下才会⽤到。
(2)typeAliases
在SQL映射文件中,select标签需要使用resultType来映射结果集,但通常需要写的返回结果集是全限定类名,带有很多包名,可以在核心配置文件中采用以下两种方式解决。
<typeAliases>
<typeAlias type="com.pojo.User" alias="user"/>
</typeAliases>
type属性:指定给哪个类起别名。alias属性:别名。当你写的是user,在SQL映射文件中不区分大小写,你可以写User、USER、user等可以写多个typeAlias标签
package
<typeAliases>
<package name="com.pojo"/>
</typeAliases>
当你有一百个类名时,需要写一百个typeAlias,这时可以采用package
在pojo包中的所有类都会自动起别名,别名就是简名类
(3)mapper
mapper不止有resource、url等属性,还有class、package
class
使用class有两个条件:
1、接口名字与映射文件名字要保持一致
2、映射文件与接口要在同一目录
<mappers>
<mapper class="com.mapper.UserMapper"/>
</mappers>
package
当有一百个接口,就要写一百个SQL映射文件,这时候就可以用package
条件与class一致
<mappers>
<package name="com.mapper"/>
</mappers>
八、MyBatis参数处理
(1)通过map集合传参
写mapper接口方法
package com.mapper;
import java.util.Map;
public interface UserMapper {
//通过map集合传参
int insertUserMap(Map<String,String> map);
}
写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.mapper.UserMapper">
<insert id="insertUserMap">
insert into t_user values(null,#{username1},#{password1})
</insert>
</mapper>
写service接口方法
package com.service;
import java.util.Map;
public interface UserService {
//通过map添加user
int insertUser(String username,String password);
}
service子类实现接口方法
package com.service.impl;
import com.mapper.UserMapper;
import com.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class UserServiceImpl implements UserService {
@Override
public int insertUser(String username,String password) {
SqlSession sqlSession = null;
try {
//可以将Sqlsession封装成工具类,就不会像下面这么复杂
sqlSession = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession();
} catch (IOException e) {
e.printStackTrace();
}
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String,String> map = new HashMap<>();
map.put("username1",username);
map.put("password1",password);
int count = mapper.insertUserMap(map);
sqlSession.commit();
return count;
}
}
写控制层get方法
package com.controller;
import com.service.UserService;
import com.service.impl.UserServiceImpl;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/first")
public class controller extends HttpServlet {
UserService userService = new UserServiceImpl();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
//获取用户名字
String username = request.getParameter("username1");
String password = request.getParameter("password1");
int count = userService.insertUser(username, password);
if (count==1){
out.print("添加成功");
}else {
out.print("添加失败");
}
}
}
写前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我的第一个web项目-mybatis</title>
</head>
<script type="text/javascript">
window.onload=function () {
document.getElementById("btn1").onclick=function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange=function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
alert(xhr.responseText)
}
}
}
var username1 = document.getElementById("username1").value;
var password1 = document.getElementById("password1").value;
xhr.open("get","/web/first?username1="+username1+"&password1="+password1,true)
xhr.send()
}
}
</script>
<body>
<h2>添加用户</h2>
请输入要添加的用户名:<input type="text" id="username1"><br>
请输入要添加的密码:<input type="text" id="password1"><br>
<input type="button" id="btn1" value="添加">
</body>
</html>
(2)实体类传参
创建一个pojo类
package com.pojo;
public class User {
String username;
String password;
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
}
添加mapper接口方法
package com.mapper;
import com.pojo.User;
public interface UserMapper {
//通过实体类传参
int insertUserPojo(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.mapper.UserMapper">
<insert id="insertUserPojo">
insert into t_user values(null,#{username},#{password})
</insert>
</mapper>
(3)@Param注解传参
添加mapper接口方法
//通过@param注解传参
List<User> selectUserParam(@Param("name") String username,@Param("pwd") String password);
添加SQL映射文件
<select id="selectUserParam" resultType="com.pojo.User">
select user_name username,user_pwd password from t_user where user_name=#{name} and user_pwd=#{pwd}
</select>
九、MyBatis查询语句专题
通常数据库和java中的映射类起的名字是不一样的,如果不采用as起别名,执行sql语句是无法映射到映射类,这里有三种解决方案:as起别名 、resultMap结果映射、开启驼峰式命名
(1)as起别名
user_name是数据库的命名规范,username是java中的命名规范(其实这里的N应该大写)
所以就会将username映射到User类中
<select id="selectUserParam" resultType="com.pojo.User">
select user_name username,user_pwd password from t_user where user_name=#{name} and user_pwd=#{pwd}
</select>
(2)使用resultMap结果映射
可以重复利用,type可以使用别名
<resultMap id="userResultMap" type="com.pojo.User">
<id property="id" column="id"/>
<result property="user_name" column="username"/>
<result property="user_pwd" column="password"/>
</resultMap>
<select id="selectUserResultMap" resultMap="userResultMap">
select user_name,user_pwd from t_user where user_name=#{username}
</select>
(3)开启驼峰式命名
在mybatis核心配置文件中配置如下,记得写在properties标签下面,没有可不管
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
实体类中的属性名 对应---> 数据库表的列名carNum car_numcarType car_typeproduceTime produce_time
十、MyBatis高级映射及延迟加载
(1)级联属性(了解)
1、创建Student、Clazz类(省略了有参无参构造、getter、setter、toString方法)
public class Student {
private Integer sid;
private String sname;
private Clazz clazz;
}
public class Clazz {
private Integer cid;
private String cname;
}
2、写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.powernode.mybatis.mapper.StudentMapper">
<resultMap id="studentResultMap" type="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<result property="clazz.cid" column="cid"/>
<result property="clazz.cname" column="cname"/>
</resultMap>
<select id="selectBySid" resultMap="studentResultMap">
select s.*, c.* from t_student s join t_clazz c on s.cid = c.cid w
here sid = #{sid}
</select>
</mapper>
3、写测试程序
public class StudentMapperTest {
@Test
public void testSelectBySid(){
StudentMapper mapper = SqlSessionUtil.openSession().getMapper(StudentMapper.class);
Student student = mapper.selectBySid(1);
System.out.println(student);
}
}
4、执行结果
(2)association
只需要修改association即可,其他地方无需修改
<resultMap id="studentResultMap" type="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz" javaType="Clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
</association>
</resultMap>
(3)分布查询
<resultMap id="studentResultMap" type="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz" select="com.powernode.mybatis.mapper.ClazzMapper.selectByCid" column="cid"/>
</resultMap>
<select id="selectBySid" resultMap="studentResultMap">
select s.* from t_student s where sid = #{sid}
</select>
在ClazzMapper接⼝中添加⽅法
public interface ClazzMapper {
Clazz selectByCid(Integer cid);
}
<?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.powernode.mybatis.mapper.ClazzMapper">
<select id="selectByCid" resultType="Clazz">
select * from t_clazz where cid = #{cid}
</select>
</mapper>
十一、MyBatis的缓存机制
(1)一级缓存
同一个 SqlSession中,执行两次相同的 sql 语句,
第一次执行完毕会将数据库中查询的数据写到缓存,第二次会直接从缓存中获取,从而提高查询效率。当一个 sqlSession 结束后该 sqlSession 中的 一级缓存也就不存在了。Mybatis 默认开启一级缓存。
sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存。手动调用sqlSession . clearCache ()也会清空缓存。
(2)二级缓存
1. <setting name="cacheEnabled" value="true"> 全局性地开启或关闭所有映射器配置⽂件中已配置的任何缓存。默认就是true,⽆需设置。2. 在需要使⽤⼆级缓存的SqlMapper.xml⽂件中添加配置:<cache />3. 使⽤⼆级缓存的实体类对象必须是可序列化的,也就是必须实现java.io.Serializable接⼝4. SqlSession对象关闭或提交之后,⼀级缓存中的数据才会被写⼊到⼆级缓存当中。此时⼆级缓存才可⽤。⼆级缓存的失效:只要两次查询之间出现了增删改操作。⼆级缓存就会失效。【⼀级缓存也会失效】
十二、MyBatis逆向工程
(1)第一步
新建module,在pom.xml文件中配置逆向工程插件
<build>
<!--可配置多个插件-->
<plugins>
<!--其中的⼀个插件:mybatis逆向⼯程插件-->
<plugin>
<!--插件的GAV坐标-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.1</version>
<!--允许覆盖-->
<configuration>
<overwrite>true</overwrite>
</configuration>
<!--插件的依赖-->
<dependencies>
<!--mysql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
(2) 第二步
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime有两个值:
MyBatis3Simple:⽣成的是基础版,只有基本的增删改查。
MyBatis3:⽣成的是增强版,除了基本的增删改查之外还有复杂的增删改查。
-->
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<!--防⽌⽣成重复代码-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<commentGenerator>
<!--是否去掉⽣成⽇期-->
<property name="suppressDate" value="true"/>
<!--是否去除注释-->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--连接数据库信息-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatisfuxi"
userId="root"
password="123456">
</jdbcConnection>
<!-- ⽣成pojo包名和位置 -->
<javaModelGenerator targetPackage="com.pojo" targetProject="src/main/java">
<!--是否开启⼦包-->
<property name="enableSubPackages" value="true"/>
<!--是否去除字段名的前后空⽩-->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- ⽣成SQL映射⽂件的包名和位置 -->
<sqlMapGenerator targetPackage="com.mapper" targetProject="src/main/resources">
<!--是否开启⼦包-->
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- ⽣成Mapper接⼝的包名和位置 -->
<javaClientGenerator
type="xmlMapper"
targetPackage="com.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 表名和对应的实体类名-->
<table tableName="t_user" domainObjectName="User"/>
</context>
</generatorConfiguration>
(3)第三步
运行插件(双击)
成功之后会自动生成项目架构
十三、MyBatis分页查询
(1)limi分页
select
*
from
tableName ......
limit
(pageNum - 1) * pageSize, pageSize
第⼀个数字:startIndex(起始下标。下标从 0 开始。)第⼆个数字:pageSize(每⻚显示的记录条数)假设已知⻚码pageNum,还有每⻚显示的记录条数pageSize,第⼀个数字可以动态的获取吗?startIndex = (pageNum - 1 ) * pageSize
(2)PageHelper插件
1、引入相关依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.1</version>
</dependency>
2、配置mybatis-config文件
在typeAliases标签中配置
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3、编写java代码
接口:
List<Car> selectAll();
SQL映射文件
<select id="selectAll" resultType="Car">
select * from t_car
</select>
@Test
public void testPageHelper() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
// 开启分⻚
PageHelper.startPage(2, 2);
// 执⾏查询语句
List<Car> cars = mapper.selectAll();
// 获取分⻚信息对象
PageInfo<Car> pageInfo = new PageInfo<>(cars, 5);
System.out.println(pageInfo);
}
十四、MyBatis注解开发
mybatis中也提供了注解开发方式,采用注解方式可以减少SQL映射文件的配置
在官方文档中,建议用注解来映射简单的SQL语句,对于复杂的SQL语句,会让你本来就复杂的SQL语句变得更加复杂,所以如果你需要做一些复杂的操作,建议采用XML来映射语句
(1)@insert
public interface CarMapper {
@Insert(value="insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})")
int insert(Car car);
}
@Test
public void testInsert() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(null, "1112", "卡罗拉", 30.0, "2000-10-10", "燃油⻋");
int count = mapper.insert(car);
System.out.println("插⼊了⼏条记录:" + count);
sqlSession.commit();
sqlSession.close();
}
(2)@delete
@Delete("delete from t_car where id = #{id}")
int deleteById(Long id);
@Test
public void testDelete() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().bu
ild(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
mapper.deleteById(89L);
sqlSession.commit();
sqlSession.close();
}
(3)@Update
@Update("update t_car set car_num=#{carNum},brand=#{brand},guide_price=#{gu
idePrice},produce_time=#{produceTime},car_type=#{carType} where id=#{id}")
int update(Car car);
@Test
public void testUpdate() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().b
uild(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(88L,"1001", "凯美瑞", 30.0,"2000-11-11", "新能源");
mapper.update(car);
sqlSession.commit();
sqlSession.close();
}
(4)@Select
@Select("select * from t_car where id = #{id}")
@Results({
@Result(column = "id", property = "id", id = true),
@Result(column = "car_num", property = "carNum"),
@Result(column = "brand", property = "brand"),
@Result(column = "guide_price", property = "guidePrice"),
@Result(column = "produce_time", property = "produceTime"),
@Result(column = "car_type", property = "carType")
})
Car selectById(Long id);
@Test
public void testSelectById() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().bu
ild(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper carMapper = sqlSession.getMapper(CarMapper.class);
Car car = carMapper.selectById(88L);
System.out.println(car);
}