MyBatis框架相关&MyBatis框架实现增删改查例子(使用XML文件配置SQL语句、动态SQL )

MyBatis框架主要作用是简化持久层开发。当使用MyBatis处理数据增删改查时,只需要定义访问数据的抽象方法,并配置该抽象方法对应的SQL语句即可!

持久层:解决项目中数据持久化处理的组件。
数据持久化:将数据永久的保存下来,即将数据存储在硬件等可以永久保存数据的存储介质中,如果要将数据保存在这些存储介质中,数据需要以文件的形式存在,通常,可以将数据存到文本文档,XML文档,数据库…通常,在没有明确的说明的情况下,讨论的就是使用数据库存取数据。

内存(RAM,具体表现通常是内存条):是CPU与其它硬件交换数据的“桥梁”,正在执行的程序和数据都在内存中,一旦断电则数据就会全部丢失。

1.创建MyBatis项目&配置相关依赖

创建Maven项目,在项目中添加相关依赖:

    <!-- java version(java依赖版本) -->
    <java.version>1.8</java.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <!-- dependency version(集中管理各个依赖的版本,下面代码配置版本时只需要"${}"提取即可) -->
    <mybatis.version>3.5.4</mybatis.version>
    <mybatis.spring.version>2.0.5</mybatis.spring.version>
    <spring.version>5.2.7.RELEASE</spring.version>
    <mysql.version>8.0.12</mysql.version>
    <druid.version>1.1.23</druid.version>
    <junit.version>4.13</junit.version>
</properties>

<dependencies>
    <!-- MyBatis:mybatis -->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <!-- MyBatis整合Spring:mybatis-spring -->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>${mybatis.spring.version}</version>
    </dependency>
    <!-- Spring:spring-context -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- Spring JDBC:spring-jdbc -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- MySQL:mysql-connector-java -->
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <!-- 连接池:druid -->
    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>${druid.version}</version>
    </dependency>
    <!-- 单元测试:junit -->
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

2.实现数据库连接配置

首先,需要在MySOL里创建数tedu_ums据库:

CREATE DATABASE tedu_ums;

然后,在项目中,在src/main/resources下创建jdbc.properties文件,用于配置连接数据库的相关信息:
spring.datasource前缀只是用来提高辨识度的!!

spring.datasource.url=jdbc:mysql://localhost:3306/tedu_ums?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.initialSize=2
spring.datasource.maxActive=10

注意根据自己的MySQL名,密码进行配置!!!

在src/main/java下创建包cn.tedu.mybatis,并在包里面创建SpringConfig类,在该类中读取以上配置文件,并·添加方法将读取的信息配置给DataSource的对象,将对象交给框架处理,最后,还需要在配置类中配置SqlSessionFactoryBean的对象,为该对象设置数据源,使得MyBatis框架能够自动获取数据库连接,并完成数据访问!:

package cn.tedu.mybatis;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.Resource;

import com.alibaba.druid.pool.DruidDataSource;
//确定根包位置
@MapperScan("cn.tedu.mybatis")
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
	
	
	@Value("${spring.datasource.url}")
	private String url;
	@Value("${spring.datasource.driver-class-name}")
	private String driverClassName;
	@Value("${spring.datasource.username}")
	private String username;
	@Value("${spring.datasource.password}")
	private String password;
	@Value("${spring.datasource.initialSize}")
	private Integer initialSize;
	@Value("${spring.datasource.maxActive}")
	private Integer maxActive;
	@Value("${mybatis.mapper-locations}")
	private Resource[] mapperlocations;
	
	@Bean
	public DataSource dataSource() {
	    // 当前项目添加依赖时
	    // 数据库连接池使用的是druid
	    // 所以,此处创建DruidDataSource的对象
	    // 如果以后改用其它数据库连接池
	    // 则创建其它数据库连接池中的对象即可
	    DruidDataSource ds = new DruidDataSource();
	    ds.setUrl(url);
	    ds.setDriverClassName(driverClassName);
	    ds.setUsername(username);
	    ds.setPassword(password);
	    ds.setInitialSize(initialSize);
	    ds.setMaxActive(maxActive);
	    return ds;
	}
	@Bean
	public SqlSessionFactoryBean sqlSessionFactoryBean(
			DataSource dataSource) {
		SqlSessionFactoryBean bean = 
				new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		bean.setMapperLocations(mapperlocations);
		return bean;
	}
	
}

3.创建数据表

在tedu_ums数据库中创建t_user数据表:

use tedu_ums;
CREATE TABLE t_user (
	id int AUTO_INCREMENT,
    username varchar(20) NOT NULL UNIQUE,
    password varchar(20) NOT NULL,
    age int,
    phone varchar(20),
    email varchar(30),
    PRIMARY KEY (id)
) DEFAULT CHARSET=utf8mb4;

4.插入、删除、修改、查询数据

4.1定义抽象方法

当使用MyBatis框架处理增删改查的时候,会需要抽象方法,我们将抽象方法定义到一个接口中**(接口名推荐使用Mapper作为结尾)**:
在cn.tedu.mybatis包中创建UserMapper接口,这个接口用于声明访问“用户"数据表中的数据:

public interface UserMapper{}

然后在接口中声明”插入用户数据"的抽象方法,关于抽象方法的声明:
返回值: 如果需要执行的是增、删、改类型的,则需要使用Integer作为返回值的类型,表示受影响的行数,当然也可以使用void作为返回值类型,表示“不关系受影响的行数",但是,并不建议这么做,如果需要执行的数据操作是查询,设计为所期望的类型即可,当然这个类型需要能够查询到的数据封装进去!

方法名称: 自定义(见名知意)

参数列表: 根据需要执行的SQL语句中的参数来决定。

当需要执行”插入用户数据"操作时,需要执行的SQL语句是:

INSERT INTO t_user(username,password,age,phone,email) VALUES(?,?,?,?,?)

可以将以上的SQL语句中的参数全部声明到抽象方法参数列表中,例如:

Integer insert (String username, String password,Integer age ,String phone,String email)

推荐使用的是将SQL语句中的参数声明到一个实体类中,然后将实体类作为抽象方法的参数:

package cn.tedu.mybatis;

public class User {

	private Integer id;
	private String username;
	private String password;
	private Integer age;
	private String phone;
	private String email;

	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 getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", password=" + password + ", age=" + age + ", phone="
				+ phone + ", email=" + email + "]";
	}

}

然后设计抽象方法:

Integer insert(User user);

抽象方法全部代码:

package cn.tedu.mybatis;

import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

public interface UserMapper {

	Integer insert(User user);

//	// 增删改返回值是受到影响的行数所以为Integer接收

	Integer deleteById(Integer id);

	Integer updatePassword(Integer password);

	Integer updateEmailByid(@Param("email") String email, @Param("id") Integer id);

	Integer count();

	User findById(Integer id);

	ArrayList<User> findAll();

	Integer deleteByIds(Integer[] ids);

	Integer updatePasswordByIds(@Param("password") String password, @Param("ids") List<Integer> ids);

}

目前,MyBatis框架并不知道接口文件的位置,就更加无法使用自定义的抽象方法,必须在配置类的声明之前添加@MapperScan注解,以指定接口文件所在的包!

4.2使用XML文件配置SQL语句

在项目的src/mian/resources下创建mappers文件夹,并创建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=" ">
</mapper>

该文件的根节点时节点,必须配置namespace的属性,该属性的值是对应的MyBatis接口文件的全名,例如:
该例子就配置了(如果疑惑待会看项目文件结构理解):

<mapper namespace="cn.tedu.mybatis.UserMapper">
</mapper>

接下来,根据需要执行的SQL语句的种类,选择使用<insert><delete><update><select>这4个节点中的某1个来配置SQL语句,这些节点都必须配置id属性,该属性的值就是接口中的抽象方法的名称,然后,在节点内部编写SQL语句即可**(UserMapper)完整代码** :

<?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="cn.tedu.mybatis.UserMapper">


	<!--id标识的是抽象方法的名称,获取自动编号的id值 useGeneratedKeys="true" keyProperty="id"-->
	<!--插入一条数据  -->
	<insert id="insert" useGeneratedKeys="true" keyProperty="id">
		INSERT
		t_user(username,password,age,phone,email)
		VALUES(#{username},#{password},#{age},#{phone},#{email})
	</insert>
	<!--根据id删除信息  -->
	<delete id="deleteById">
	    DELETE FROM t_user WHERE id=#{id}
	</delete>
	<!--修改密码  -->
	<update id="updatePassword">
	    UPDATE t_user SET password=#{password}
	</update>
	<!--根据id修改邮箱  -->
	<update id="updateEmailByid">
	    UPDATE t_user SET email=#{email} WHERE id=#{id}
	</update>
	<!--统计表中的数据条数  -->
	<select id="count" resultType="java.lang.Integer">
		SELECT COUNT(*) FROM t_user
	</select>
    <!--根据id查询信息  -->
	<select id="findById" resultType="cn.tedu.mybatis.User">
	SELECT * FROM t_user WHERE id=#{id}
	</select>
	<!--查询所有id分组  -->
	<select id="findAll" resultType="cn.tedu.mybatis.User">
		SELECT * FROM t_user ORDER BY id
	</select>
    <!--根据id批量删除  -->
	<delete id="deleteByIds">
		delete from t_user where id in(
		<foreach collection="array" item="id" separator=",">
			#{id}
		</foreach>
		)
	</delete>

	<update id="updatePasswordByIds">
		update t_user set password=#{password} where id in(
		<foreach collection="ids" item="id" separator=",">
			#{id}</foreach>
		)
	</update>
</mapper>

resultType`指的就是“封装查询结果的数据的类型”,也可以理解为“抽象方法的返回值的类型”,例如可以配置为:

<select id="count" resultType="java.lang.Integer">
	SELECT COUNT(*) FROM t_user
</select>

如果某个查询的抽象方法的返回值是List集合类型的,例如:

List<User> findAll();

在配置<select>resultType属性时,该属性值必须是集合中的元素的类型,例如:

<select id="findAll" resultType="cn.tedu.mybatis.User">
    SELECT * FROM t_user ORDER BY id
</select>

至于resultMap属性,后面专门介绍。

注意:使用了这种做法后,就需要对抽象方法名称的定义增加一个要求“不允许重载”!

4.2.1 关于多参数的问题

当抽象方法的参数列表中超过1个参数时,在配置SQL语句时直接使用#{参数名称}是无法访问到参数值的!

因为Java源文件在运行之前需要被编译成字节码文件(.class文件),编译时,会丢失所有局部的量的名称,所以,会导致运行时原有的“参数名称”无法使用的问题!

MyBatis允许使用arg作为前缀并添加从0开始编号的名称(例如arg0arg1等等)表示第?个参数的名称,后续,在配置SQL语句时,就可以通过例如#{arg0}来表示抽象方法的第1个参数的值,使用#{arg1}表示抽象方法的第2个参数的值……以此类推!另外,还可以使用param作为前缀并添加从1开始编号的名称(例如param1param2等等),在具体使用时,使用arg系列的名称和param系列的名称均可!

但是,使用argparam 系列的名称不便于表示语义,并且,当抽象方法的参数列表发生变化时,这些名称中的序号也可能需要调整!

MyBatis提供了@Param注解,这个注解是添加在抽象方法的各参数之前的,可以在该注解中指定名称,后续,在配置SQL语句时,占位符中就使用注解中配置的名称!

4.2.2 动态SQL – foreach

假设存在需求:批量删除用户数据(一次性删除若干条用户数据);

需要执行的SQL语句大致是:

DELETE FROM t_user WHERE id=? OR id=? OR id=?;
DELETE FROM t_user WHERE id IN (?,?,?);

作为开发人员,无法确定以上SQL语句中问号的数量,及问号对应的参数值!只能确定以上参数的数据类型及所表示的意义!

以上功能最终将由用户(软件的使用者)来决定需要删除的数据的数量(问号的数量),及删除的数据是哪几条(问号对应的参数值)!就会导致“当用户的操作不同时(选中需要删除的数据不同),最终需要执行的SQL语句是不同的”!MyBatis框架提供了“动态SQL”机制来解决这个问题!

动态SQL:根据用户提供的参数值不同,最终需要执行的SQL语句可以不同!

当需要实现以上批量删除的需求时,可以将抽象方法设计为:

Integer deleteByIds(List<Integer> ids);

或者,也可以设计为(本次案例就使用这个):

Integer deleteByIds(Integer[] ids);

甚至,还可以设计为:

Integer deleteByIds(Integer... ids);

可变参数在被处理时,本质上就是数据。

在配置SQL语句时,需要通过<foreach>节点来配置SQL语句中需要通过循环生成的部分:

<delete id="deleteByIds">
    DELETE FROM t_user WHERE id IN (
    	<foreach collection="array" item="id" separator=",">
            #{id}
    	</foreach>
    )
</delete>

关于<foreach>节点的配置:

  • collection:需要被遍历的对象,当抽象方法的参数只有1个且没有添加@Param注解时,如果参数类型是List集合,则取值为list,如果参数类型是数组,则取值为array;当抽象方法的参数超过1个,就一定添加了@Param注解,则取值为@Param注解配置的参数值;

  • item:遍历过程中的每一个元素数据,当前属性可以自定义值表示元素数据的名称,在<foreach>节点的子级,使用#{}占位符时,就可以使用这个名称来表示数据;

  • separator:遍历生成的代码片段中,各元素数据之间的分隔符号。

5.添加测试文件

接下来,在src/test/java下创建cn.tedu.mybatis包,并在这个包中创建``UserMapperTests`测试类,并测试以上方法:

package cn.tedu.mybatis;

import java.util.ArrayList;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class UserMapperTests {

	private AnnotationConfigApplicationContext ac;
	private UserMapper userMapper;

	// 插入数据
	@Test
	public void insert() {
		User user = new User();
		user.setUsername("poot");
		user.setPassword("1234");
		user.setAge(22);
		user.setPhone("12344556677");
		user.setEmail("root@.com");
		System.out.println(user);
		Integer rows = userMapper.insert(user);
		System.out.println(user);
		System.out.println("插入了" + rows + "条数据!");

	}

	// 删除数据
	@Test
	public void delete() {

		Integer id = 1;
		Integer rows = userMapper.deleteById(id);
		System.out.println("删除了" + rows + "条数据!");

	}

	// 更新数据
	@Test
	public void update() {
		Integer password = 1;
		Integer rows = userMapper.updatePassword(password);
		System.out.println("更新了" + rows + "条数据!");

	}

	// 跟据id修改邮箱
	@Test
	public void updateEmailByid() {
		String email = "123wewe@.com";
		Integer id = 3;
		Integer rows = userMapper.updateEmailByid(email, id);
		System.out.println("成功修改了" + rows + "条数据!");

	}

//统计表中人数
	@Test
	public void count() {
		Integer count = userMapper.count();
		System.out.println("表中有" + count + "条数据");
	}

	// 通过id查询
	@Test
	public void findById() {
		Integer id = 3;
		User user = userMapper.findById(id);
		System.out.println("user=" + user);
	}

	// 表中人的所有信息
	@Test
	public void findAll() {
		ArrayList<User> array = userMapper.findAll();
		System.out.println("array=" + array.size());

	}

	// 根据id批量删除
	@Test
	public void deleteByIds() {
		Integer[] ids = { 4, 5, 8 };
		Integer rows = userMapper.deleteByIds(ids);
		System.out.println("一共删除了用户表的" + rows + "个字段");
	}

	// 根据id批量修改
	@Test
	public void updatePasswordByIds() {
		List<Integer> ids = new ArrayList<Integer>();
		ids.add(6);
		ids.add(9);
		String password = "abcd";
		Integer rows = userMapper.updatePasswordByIds(password, ids);
		System.out.println("一共修改了用户表的" + rows + "个字段");
	}

	// 资源加载,数据库操作前先加载
	@Before
	public void doBefore() {
		ac = new AnnotationConfigApplicationContext(SpringConfig.class);
		userMapper = ac.getBean("userMapper", UserMapper.class);
	}

	// 资源关闭,数据库操作完后关闭
	@After
	public void doAfter() {
		ac.close();
	}
}

6.文件目录结构:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值