目录
前言
一、回顾JDBC操作数据库的过程
二、Mybatis操作数据库的过程
三、上代码
1.引入库
2.创建User.java
3.创建UserMapper.java
4.创建UserMapper.xml
5.创建Mybatis核心配置文件mybatis-config.xml
6.创建测试类UserServiceTest.java
7.运行测试
四、mybatisX插件的安装
前言
springboot项目结构:
一、回顾JDBC操作数据库的过程
使用JDBC链接,操作数据库的过程:
1. 加载JDBC驱动
2. 建立并获取数据库链接
3. 创建JDBC Statements 对象
4. 设置SQL 语句的传入参数
5. 执行SQL 语句并获取查询结果
6. 对查询结果进行转换处理并将处理结果返回
7. 释放相关资源(关闭Connection,关闭Statement,关闭ResultSet)
JDBC的问题:
1. 频繁的链接、关闭数据库,浪费数据库资源、影响性能(可以用连接池优化)
2. SQL语句散落在代码中,不断地拼入参,重复代码较多。(Mybatis中有变量名参数、动态SQL及SQL语句统一存放)
3. 得到结果后大量需要结果属性映射及封装。(Mybatis中SQL处理器直接返回需要的类型对象,完成数据结构及结果的映射)
二、Mybatis操作数据库的过程
使用Mybatis直接链接数据库操作数据
1. 建立对应表的用户实体类(普通的java bean)User.java
2. 定义DAO接口(也就是Mapper映射接口),与数据库交互作用:UserMapper.java
3. 创建统一写sql语句的XML文件与DAO接口(也就是Mapper映射接口)对应,路径包名要一致,XML文件与数据层接口类的名称一致,UserMapper.xml
4. 建立Mybatis核心配置文件mybatis-config.xml,在resources文件包下。配置文件中定义了数据源、数据层映射接口与SQL语句的XML文件的映射关系等
三、上代码
1.引入库
maven的pom.xml引入库
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>mybatis_demo2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis_demo2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!--分页插件包引入-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
<!--添加log4j日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.mybatis_demo2.MybatisDemo2Application</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2.创建User.java
package com.mybatis_demo2.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author lv
* @date 2022年11月12日22点00分
* 封装数据的实体bean,(lombok简化代码)
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String nickname;
private Date addtime;
}
3.创建UserMapper.java
package com.mybatis_demo2.mapper;
import com.github.pagehelper.Page;
import com.mybatis_demo2.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author lv
* @date 2022年11月12日17点24分
* dao层,主要负责和数据库交互
*/
public interface UserMapper {
/**
* 查询所有用户信息
* @return
*/
public List<User> selectUserAll();
/**
* 查询单个用户
* @param id
* @return
*/
public User selectOneUser(int id);
/**
* 添加数据
* @param user
* @return
*/
public int adduser(User user);
/**
* 更新数据
* @param user
* @return
*/
public int update(User user);
/**
* 删除数据
* @param id
* @return
*/
public int del(Integer id);
/**
* 查询分页总条数(普通分页方式)
* @return
*/
Long countAllUser();
/**
* 查询每页的显示数据(普通分页方式)
* @param index LIMIT函数的起始索引值
* @param size LIMIT函数的每页大小
* @return
*/
List<User> selectPageUser(@Param("index") int index, @Param("size") int size);
/**
* 使用分页插件实现分页查询
* @return
*/
Page<User> pagePluginselectUser();
/**
* 查询单个用户(根据用户名查询,演示SQL注入)
* @param username
* @return
*/
User findUsernameUser(String username);
/**
* 据id查询用户(使用标签,在UserMapper.xml中使用where和if标签)
* @param id
* @return
*/
List<User> findUserList(int id);
/**
* 根据username查询用户(使用标签,在UserMapper.xml中使用where,if和 foreach 标签)
* @Param("unamelist") 定义参数名,方便UserMapper.xml找到参数
* @param unamelist
* @return
*/
List<User> findUserListByUsername(@Param("unamelist") List<String> unamelist);
}
4.创建UserMapper.xml
注意:在resources资源文件夹下创建com\mybatis_demo2\mapper目录,逐层单个建立,不能在idea中com.mybatis_demo2.mapper直接建立。然后从磁盘重新刷新加载项目。血泪史切记
<?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">
<!--命名空间映射到UserMapper类-->
<mapper namespace="com.mybatis_demo2.mapper.UserMapper">
<!--public List<User> selectUserAll();方法的映射对应id="selectAll",resultType返回类型为User POJO类-->
<select id="selectUserAll" resultType="com.mybatis_demo2.pojo.User">
select * from users
</select>
<!--public User selectOneUser(int id);(int id)和#{id}对应-->
<select id="selectOneUser" parameterType="int" resultType="com.mybatis_demo2.pojo.User">
select * from users where id=#{id}
</select>
<!--public int adduser(User user);-->
<insert id="adduser" parameterType="com.mybatis_demo2.pojo.User" useGeneratedKeys="true" keyProperty="id">
insert into users(username,password,nickname,addtime) values(#{username},#{password},#{nickname},NOW())
</insert>
<!--public int update(User user);-->
<update id="update" parameterType="com.mybatis_demo2.pojo.User">
update users set username=#{username} where id=#{id}
</update>
<!--public int del(Integer id);-->
<delete id="del" parameterType="integer">
delete from users where id=#{id}
</delete>
<!--Long countAllUser();-->
<select id="countAllUser" resultType="long">
select COUNT(id) from users
</select>
<!--ist<User> selectPageUser(@param(index) int index,@param(size) int size);-->
<select id="selectPageUser" parameterType="java.util.Map" resultType="com.mybatis_demo2.pojo.User">
select * from users order by id desc LIMIT #{index},#{size}
</select>
<!--Page<User> pagePluginselectUser();-->
<select id="pagePluginselectUser" resultType="com.mybatis_demo2.pojo.User">
select * from users
</select>
<!--User findUsernameUser(String username);-->
<select id="findUsernameUser" parameterType="string" resultType="com.mybatis_demo2.pojo.User">
select * from users where username=${username}
</select>
<!--List<User> findUserList(int id);-->
<select id="findUserList" parameterType="int" resultType="com.mybatis_demo2.pojo.User">
select * from users
<where>
<if test="id >2">
and id>2
</if>
<if test="id < 5">
and id < 7
</if>
</where>
</select>
<!--List<User> findUserListByUsername(@Param("unamelist") List<String> unamelist); foreach中的item定义条件字段项 -->
<select id="findUserListByUsername" parameterType="list" resultMap="userMap">
select * from users
<where>
<if test="unamelist!=null and unamelist.size>0">
username in
<foreach collection="unamelist" item="username" separator="," open="(" close=")">
${username}
</foreach>
</if>
</where>
</select>
<!--resultMap的使用,映射数据库表和实体bean的字段值对应关系. id="userMap" 在上面findUserListByUsername查询中被引用-->
<resultMap id="userMap" type="com.mybatis_demo2.pojo.User">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="nickname" property="nickname"></result>
<result column="addtime" property="addtime"></result>
</resultMap>
</mapper>
5.创建Mybatis核心配置文件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>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<plugins>
<!--分页插件,指定使用特定的拦截器com.github.pagehelper.PageInterceptor-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<!--数据源配置-->
<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/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--将UserMapper.xml装载进来与UserMapper.java对应,映射。并建立UserMapper接口类的实现类-->
<mapper resource="com/mybatis_demo2/mapper/UserMapper.xml"/>
<!--也可以使用包路径映射整个XML文件的目录路径,如下-->
<!--<package name="com.mybatis_demo2.mapper"/>-->
</mappers>
</configuration>
6.创建测试类UserServiceTest.java
package com.mybatis_demo2;
import com.mybatis_demo2.pojo.User;
import com.mybatis_demo2.service.impl.UserService;
import org.apache.log4j.Logger;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
/**
* @author lv
* @date 2022年11月12日23点41分
* 测试用例类
*/
public class UserServiceTest {
private Logger logger = Logger.getLogger(this.getClass());
/**
* 使用JDBC链接,操作数据库的过程
* 1. 加载JDBC驱动
* 2. 建立并获取数据库链接
* 3. 创建JDBC Statements 对象
* 4. 设置SQL 语句的传入参数
* 5. 执行SQL 语句并获取查询结果
* 6. 对查询结果进行转换处理并将处理结果返回
* 7. 释放相关资源(关闭Connection,关闭Statement,关闭ResultSet)
*/
/**
* 使用Mybatis直接链接数据库操作数据
* 1. 建立对应表的用户实体类(普通的java bean)User.java
* 2. 定义DAO接口(也就是Mapper映射接口),与数据库交互作用:UserMapper.java
* 3. 创建统一写sql语句的XML文件与DAO接口(也就是Mapper映射接口)对应,路径报名要一致,XML文件与数据层接口类的名称一致,UserMapper.xml
* 4. 建立Mybatis核心配置文件mybatis-config.xml,在resources文件包下。配置文件中定义了数据源、数据层映射接口与SQL语句的XML文件的映射关系等
* 5. 测试
*/
@Test
public void testSelectAlluser(){
UserService userService=new UserService();
/**
* 查询所有字段时如果User用户封装实体中有字段与表中字段不一致,得到的字段显示结果为null
* 解决方法为:使用as关键字取别名进行关联映射,select id_card as idCard from users
*/
List<User> list= userService.selectAlluser();
if(list.size()>0){
// //for迭代循环
// for(User user:list){
// System.out.println(user.getUsername()+"||"+user.getPassword()+"||"+user.getNickname());
// }
// //for循环,语法格式:for (①初始化部分; ②循环条件部分; ④迭代部分){ ③循环体部分; }
// for(int i=0;i<list.size();i++){
// User user=list.get(i);
// System.out.println(user.getId()+"||"+user.getUsername()+"||"+user.getPassword()+"||"+user.getNickname());
// }
// //while循环,语法:①初始化部分 while(②循环条件部分){ ③循环体部分; ④迭代部分; }
// int i=0;
// while (i<list.size()){
// User user=list.get(i);
// System.out.println(user.getUsername()+"||"+user.getPassword());
// i++;
// }
//do-while循环至少执行一次循环体,语法:①初始化部分; do{ ③循环体部分 ④迭代部分 }while(②循环条件部分);
int i=0;
do{
User user=list.get(i);
System.out.println(user.getId()+"||"+user.getUsername());
i++;
}while (i<list.size());
}else{
System.out.println(userService.selectAlluser().size());
}
}
@Test
public void selectUserOne(){
UserService userService=new UserService();
User user=userService.selectUserOne(3);
System.out.println("获得用户明细:"+user.getUsername()+"----"+user.getId());
logger.info("log4j获得用户明细:"+user.getUsername()+"----"+user.getId());
}
@Test
public void addOneUser(){
UserService userService=new UserService();
User user=new User();
user.setUsername("user008");
user.setPassword("12345");
user.setNickname("坍台灭明");
boolean bol=userService.adduser(user);
System.out.println("--------"+user);
logger.info("log4j获得bol:"+bol);
}
/**
* 更新操作,业务层报异常后事务回滚操作
*/
@Test
public void upOneUser(){
UserService userService=new UserService();
User user=new User();
user.setId(17);
user.setUsername("user0017002");
boolean bol=userService.updateUser(user);
System.out.println("--------"+user);
logger.info("log4j获得bol:"+bol);
}
@Test
public void delOneUser(){
UserService userService=new UserService();
boolean bol=userService.delUser(14);
logger.info("log4j获得bol:"+bol);
}
/**
* 普通分页
*/
@Test
public void pageSelect(){
UserService userService=new UserService();
List<User> list= userService.selectPageUser(3,4);
}
/**
* 分页插件简化分页
* 1. 向pom.xml中添加依赖包
* <!--分页插件包引入-->
* <dependency>
* <groupId>com.github.pagehelper</groupId>
* <artifactId>pagehelper</artifactId>
* <version>5.2.0</version>
* </dependency>
* 2. 向 mybatis-config.xml 核心配置文件中加入插件拦截器
* <plugins>
* <!--分页插件-->
* <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
* </plugins>
* 3. 使用分页插件传入分页参数,只有紧跟startPage()方法之后的查询语句才会被执行分页
* PageHelper.startPage(pageNum,size); --pageNum:第几页,size每页分页大小
* 4. 调用分页查询的方法,使用Page<E> 或 PageInfo<T>
* Page<User> pageUser= mapper.pagePluginselectUser();
* 或
* userlist= mapper.selectUserAll();
* PageInfo<User> pinfo=new PageInfo<>(userlist,1);
*/
@Test
public void pagePluginSelect(){
UserService userService=new UserService();
List<User> list= userService.PagePluginUserSelect(3,3);
}
/**
* 查询单个用户(根据用户名查询,演示SQL注入)
*/
@Test
public void findUsernameUser(){
UserService userService=new UserService();
/**
* findUsernameUser(String username)调用此方法时正确的参数是传入一个username,但是实际我传入了一个字符串,模拟进行了SQL注入。
* 运行后打印的结果为:
* Preparing: select * from users where username='user001' and username='mm'
* Parameters:
* Total: 0
* UserMapper.xml文件中SQL语句为:select * from users where username=${username}
*
* -------改进避免SQL注入
* 将UserMapper.xml文件中SQL语句改为:select * from users where username=#{username} --Mybatis中使用#{}传参避免了SQL注入。
* 运行后打印的结果为:
* Preparing: select * from users where username=?
* Parameters: 'user001' and username='mm'(String)
* Total: 0
*/
userService.findUsernameUser("'user001' and username='mm'");
}
/**
* 根据id查询用户(使用标签,在UserMapper.xml中使用where和if标签)
*/
@Test
public void testGetListUser(){
UserService userService=new UserService();
userService.findListUser(3);
}
/**
* 根据username查询用户(使用标签,在UserMapper.xml中使用where,if和 foreach 标签)
*/
@Test
public void testfindUserListByUname(){
UserService userService=new UserService();
List<String> unamelist=new ArrayList<>();
unamelist.add("'user02'");
unamelist.add("'user003'");
unamelist.add("'user005'");
userService.findUserListByUname(unamelist);
}
/**
* 附加
* 打印99乘法表
*/
@Test
public void multiplyTable(){
// for(int i=1;i<10;i++){
// for(int j=1;j<(i+1);j++){
// System.out.print(j+"*"+i+"="+(j*i)+" ");
// if((j*i==6||j*i==8)&&(i==3||i==4)){
// System.out.print(" ");
// }
// }
// //println()换行,print()不换行
// System.out.println();
// }
int a= 8%2;
System.out.println(a>0 ? 8/2+1 : 8/2);
}
}
7.运行测试
测试运行selectUserOne()测试方法的运行接口如下:
四、mybatisX插件的安装
使用mybatisX插件可以实现在UserMapper.xml和UserMapper.java文件之间的关联切换