Mybatis的开发有两种⽅式
一种是注解 一种就是XML
我们使用Mybatis的注解方式主要完成一些简单的cuda,但如果要完成较为复杂的sql功能,建议使用xml来配置映射语句,就是将sql语句写在xml配置文件中.
MyBatis XML的方式有以下两步:
(1) 配置数据库连接字符串和Mybatis
(2) 写持久层代码
配置连接字符串和MyBatis
这步骤需要进行两项设置 设置MyBatis的XML文件配置(连接字符串设置)
application.yml配置内容:
#数据库连接配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
configuration: #配置打印MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
#配置 mybatis xml的文件路径 在resources/mapper创建所有表的xml文件
mapper-locations: classpath:mapper/**Mapper.xml
写持久层代码
方法定义 Interface
方法实现 XXX.xml
添加mapper接口
数据持久层的接口定义:(方法定义)
添加UserInfoXMLMapper.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.example.mybatisdemo.demos.web.mapper.UserInfoXMLMapper">
<select id="queryAllUser" resultType="com.example.mybatisdemo.demos.web.model.UserInfo">
select username, password,age,gender,phone from userinfo
</select>
</mapper>
标签说明:
<mapper>标签:需要指定namespace属性,表示命名空间值为 mapper 接⼝的全限定名,包括全包名.类名
<select>查询标签:执行sql查询语句
id:和interface定义方法名称一样表示对接口的具体实现
resultType:返回的数据类型 我们定义的实体类
单元测试:
package com.example.mybatisdemo.demos.web.mapper;
import com.example.mybatisdemo.demos.web.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@Slf4j
@SpringBootTest
class UserInfoXMLMapperTest {
@Autowired
private UserInfoXMLMapper userInfoXMLMapper;
@Test
void queryAllUser() {
List<UserInfo> userInfoList = userInfoXMLMapper.queryAllUser();
log.info(userInfoList.toString());
}
}
测试类:
package com.example.mybatisdemo.demos.web.mapper;
import com.example.mybatisdemo.demos.web.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@Slf4j
@SpringBootTest
class UserInfoXMLMapperTest {
@Autowired
private UserInfoXMLMapper userInfoXMLMapper;
@Test
void queryAllUser() {
List<UserInfo> userInfoList = userInfoXMLMapper.queryAllUser();
log.info(userInfoList.toString());
}
}
结果:
出错记录:
之前我的配置没有问题但还是一直说找不到对应的接口
这时因为有两个配置文件 其中一个yml的配置mapper文件方式是对的 但是另一个pro文件也有一个自动生成的对不上 当两个配置文件同时存在时就会优先生效pro文件
实现增删查改操作
增
UserInfoMapper接口:
Integer insertUser(UserInfo userInfo);
UserInfoMapper.xml实现:
<insert id="insertUser">
insert into userinfo (username,password,age,gender,phone)
values (#{username}, #{password}, #{age},#{gender},#{phone})
</insert>
测试接口:
@Test
void insertUser() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("xiaoming");
userInfo.setPassword("123456");
userInfo.setAge(12);
userInfo.setGender(1);
userInfo.setPhone("111111111111");
Integer result = userInfoXMLMapper.insertUser(userInfo);
if (result>0){
log.info("执行成功");
}
结果
使⽤@Param设置参数名称
Integer inserUser2(@Param("userinfo") UserInfo userInfo);
UserInfoMapper.xml实现:
<insert id="inserUser2">
insert into userinfo (username,password,age,gender,phone)
values (#{userinfo.username},#{userinfo.password},#{userinfo.age},#{userinfo.},#{userinfo.gender},#{userinfo.phone})
</insert>
返回自增id
Mapper.xml 实现 设置useGeneratedKeys 和keyProperty属性
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into userinfo (username,password,age,gender,phone)
values (#{username}, #{password}, #{age},#{gender},#{phone})
</insert>
删
接口
Integer deleteUser(Integer id);
xml实现
<delete id="deleteUser">
delete from userinfo where id = #{id}
</delete>
改
接口
Integer updateUser(UserInfo userInfo);
xml实现
<update id="updateUser">
update userinfo set username=#{username} where id=#{id}
</update>
查
使用xml方式查询也存在数据封装的问题
我们把SQL语句进⾏简单修改, 查询更多的字段内容
它的解决方法和注解类似
(1)起别名
(2)结果映射
(3)开启驼峰命名
xml的结果映射
<resultMap id="BeseMap" type="com.example.mybatisdemo.demos.web.model.UserInfo">
<id column="id" property="id"></id>
<result column="dele_flag" property="deleteFlag"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
</resultMap>
<select id="queryAllUser1" resultMap="BeseMap" >
select id, username,password, age, gender, phone, delete_flag,
create_time, update_time from userinfo
</select>
测试代码
@Test
void queryAllUser1() {
List<UserInfo> userInfoList = userInfoXMLMapper.queryAllUser();
log.info(userInfoList.toString());
}
结果:
其他查询操作
多表查询
多表查询和单表查询类似, 只是SQL不同⽽已
准备⼯作
我们建立一张文章表进行多表查询
对应的model
package com.example.mybatisdemo.demos.web.model;
import lombok.Data;
import java.util.Date;
@Data
public class ArticleInfo {
private Integer id;
private String tetle;
private String content;
private Integer uid;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
//用户信息
private String username;
private Integer age;
private Integer gender;
}
查询:
根据uid查询作者的名称等相关信息
sql语句:
select ta.id,ta.title,ta.content,ta.uid,tb.username,ta.age,tb.gender, from articleinfo ta left join userinfo tb on ta.uid = tb.id
where ta.id =1;
定义接口
package com.example.mybatisdemo.demos.web.mapper;
import com.example.mybatisdemo.demos.web.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface ArticleInfoMapper {
@Select("ta.id,ta.title,ta.content,ta.uid,tb.username,ta.age,tb.gender, from articleinfo ta left join userinfo tb on ta.uid = tb.id\n" +
"where ta.id =#{id}")
ArticleInfo queryUserByUid(Integer id);
}
生成测试类
package com.example.mybatisdemo.demos.web.mapper;
import com.example.mybatisdemo.demos.web.model.ArticleInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.*;
@Slf4j
@SpringBootTest
class ArticleInfoMapperTest {
@Autowired
private ArticleInfoMapper articleInfoMapper;
@Test
void queryUserByUid() {
ArticleInfo articleInfo = articleInfoMapper.queryUserByUid(1);
log.info(articleInfo.toString());
}
}
结果和数据库查询的一样
注意:
在实际中应该避免使用夺表查询 特别是队性能要求很高的项目 因为一般情况下,数据库集群是很多项目一起使用的,当出现慢查询的时候
会影响整个集群 就会影响所有使用改集群的项目
sql中直接查询多个表把查询的结果放在一个对象中
@Select("select ta.*, tb.username,tb.age from articleinfo ta" +
" LEFT JOIN userinfo tb on ta.uid = tb.id" +
" where ta.id=1")
ArticleInfo queryUserByUid1(Integer id);