1. 后端程序2. 数据库
1. 创建数据库连接池 DataSource2. 通过 DataSource 获取数据库连接 Connection3. 编写要执行带 ? 占位符的 SQL 语句4. 通过 Connection 及 SQL 创建操作命令对象 Statement5. 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值6. 使用 Statement 执行 SQL 语句7. 查询操作:返回结果集 ResultSet ,更新操作:返回更新的数量8. 处理结果集9. 释放资源
-- 创建数据库
create database if not exists `library` default character set utf8mb4;
-- 使用数据库
use library;
-- 创建表
create table if not exists `soft_bookrack` (
`book_name` varchar(32) NOT NULL,
`book_author` varchar(32) NOT NULL,
`book_isbn` varchar(32) NOT NULL primary key
) ;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SimpleJdbcOperation {
private final DataSource dataSource;
public SimpleJdbcOperation(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 添加一本书
*/
public void addBook() {
Connection connection = null;
PreparedStatement stmt = null;
try {
//获取数据库连接
connection = dataSource.getConnection();
//创建语句
stmt = connection.prepareStatement(
"insert into soft_bookrack (book_name, book_author, book_isbn) values (?,?,?);"
);
//参数绑定
stmt.setString(1, "Spring in Action");
stmt.setString(2, "Craig Walls");
stmt.setString(3, "9787115417305");
//执行语句
stmt.execute();
} catch (SQLException e) {
//处理异常信息
} finally {
//清理资源
try {
if (stmt != null) {
stmt.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
//
}
}
}
/**
* 更新一本书
*/
public void updateBook() {
Connection connection = null;
PreparedStatement stmt = null;
try {
//获取数据库连接
connection = dataSource.getConnection();
//创建语句
stmt = connection.prepareStatement(
"update soft_bookrack set book_author=? where book_isbn=?;"
);
//参数绑定
stmt.setString(1, "张卫滨");
stmt.setString(2, "9787115417305");
//执行语句
stmt.execute();
} catch (SQLException e) {
//处理异常信息
} finally {
//清理资源
try {
if (stmt != null) {
stmt.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
//
}
}
}
/**
* 查询一本书
*/
public void queryBook() {
Connection connection = null;
PreparedStatement stmt = null;
ResultSet rs = null;
Book book = null;
try {
//获取数据库连接
connection = dataSource.getConnection();
//创建语句
stmt = connection.prepareStatement(
"select book_name, book_author, book_isbn from soft_bookrack where book_isbn =?"
);
//参数绑定
stmt.setString(1, "9787115417305");
//执行语句
rs = stmt.executeQuery();
if (rs.next()) {
book = new Book();
book.setName(rs.getString("book_name"));
book.setAuthor(rs.getString("book_author"));
book.setIsbn(rs.getString("book_isbn"));
}
System.out.println(book);
} catch (SQLException e) {
//处理异常信息
} finally {
//清理资源
try {
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
//
}
}
}
public static class Book {
private String name;
private String author;
private String isbn;
//省略 setter getter 方法
}
}
- 配置 MyBatis 开发环境;
- 使用 MyBatis 模式和语法操作数据库。
1. 将输入数据(即传入对象) +SQL 映射成原生 SQL2. 将结果集映射为返回对象,即输出对象
- 数据库表(table)--> 类(class)
- 记录(record,行数据)--> 对象(object)
- 字段(field) --> 对象的属性(attribute)
-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8;
-- 使用数据数据
use mycnblog;
-- 创建表[用户表]
drop table if exists userinfo;
create table userinfo(
id int primary key auto_increment,
username varchar(100) not null,
password varchar(32) not null,
photo varchar(500) default '',
createtime datetime default now(),
updatetime datetime default now(),
`state` int default 1
);
-- 创建文章表
drop table if exists articleinfo;
create table articleinfo(
id int primary key auto_increment,
title varchar(100) not null,
content text not null,
createtime datetime default now(),
updatetime datetime default now(),
uid int not null,
rcount int not null default 1,
`state` int default 1
);
-- 创建视频表
drop table if exists videoinfo;
create table videoinfo(
vid int primary key,
`title` varchar(250),
`url` varchar(1000),
createtime datetime default now(),
updatetime datetime default now(),
uid int
);
-- 添加一个用户信息
INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`)
VALUES
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);
-- 文章添加测试数据
insert into articleinfo(title,content,uid)
values('Java','Java正文',1);
-- 添加视频
insert into videoinfo(vid,title,url,uid) values(1,'java title','http://www.baidu.com',1);
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.4
mysql
mysql-connector-java
runtime
EditStarters 插件的使用方法:
如果是新项目创建 Spring Boot 项目的时候添加引用就可以了,如下图所示:
# 数据库连接配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置 mybatis xml 的文件路径,在 resources/mapper 创建所有表的 xml 文件
mybatis:
mapper-locations: classpath:mapper/**Mapper.xml
下面按照后端开发的工程思路,也就是下面的流程来实现 MyBatis 查询所有用户的功能:
import lombok.Data;
import java.util.Date;
@Data
public class User {
private Integer id;
private String username;
private String password;
private String photo;
private Date createTime;
private Date updateTime;
}
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
public List getAll();
}
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserService {
@Resource
private UserMapper userMapper;
public List getAll() {
return userMapper.getAll();
}
}
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/u")
public class UserController {
@Resource
private UserService userService;
@RequestMapping("/getall")
public List getAll(){
return userService.getAll();
}
}
- 标签:插入语句
- 标签:修改语句
- 标签:删除语句
@RequestMapping(value = "/add",method = RequestMethod.POST)
public Integer add(@RequestBody User user){
return userService.getAdd(user);
}
Integer add(User user);
insert into userinfo(username,password,photo,state)
values(#{username},#{password},#{photo},1)
Postman 添加访问:
{"username":"mysql","password":"mysql","photo":"img.png"}
@RequestMapping(value = "/add2", method = RequestMethod.POST)
public Integer add2(@RequestBody User user) {
userService.getAdd2(user);
return user.getId();
}
@Mapper
public interface UserMapper {
// 添加,返回自增id
void add2(User user);
}
insert into userinfo(username,password,photo,state)
values(#{username},#{password},#{photo},1)
/**
* 修改操作
*
* @param id
* @param name
* @return
*/
@RequestMapping("/update")
public Integer update(Integer id, String name) {
return userService.update(id, name);
}
update userinfo set username=#{name} where id=#{id}
delete from userinfo where id=#{id}
@RequestMapping("/getuser")
public User getUserById(Integer id) {
return userService.getUserById(id);
}
- #{}:预编译处理。
- ${}:字符直接替换。
而直接替换的情况相当于,头等舱和经济舱不分离的情况,这样经济舱的乘客在通过安检之后可能越权摸到头等舱,如下图所示:
查询不设置返回类型的错误示例演示
@RequestMapping("/getname")
public String getNameById(Integer id) {
return userService.getNameById(id);
}
resultMap 使用场景:
- 字段名称和程序中的属性名不同的情况,可使用 resultMap 配置映射;
- 一对一和一对多关系可以使用 resultMap 映射并查询数据。
程序中的属性如下:
mapper.xml 代码如下:
查询的结果如下:
这个时候就可以使用 resultMap 了,resultMap 的使用如下:
mapper.xml
查询的结果就有值了,如下图所示:
一对一映射要使用 标签,具体实现如下(一篇文章只对应一个作者):
- property 属性:指定 Article 中对应的属性,即用户。
- resultMap 属性:指定关联的结果集映射,将基于该映射配置来组织用户数据。
- columnPrefix 属性:绑定一对一对象时,是通过 columnPrefix+association.resultMap.column 来映射结果集字段。association.resultMap.column是指 标签中 resultMap属性,对应的结果集映射中,column字段。
import java.time.LocalDateTime;
@Data
public class ArticleInfo {
private Integer id;
private String title;
private String content;
private LocalDateTime createtime;
private LocalDateTime updatetime;
private Integer rcount;
private User user;
}
import com.example.demo.model.ArticleInfo;
import com.example.demo.service.ArticleService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RequestMapping("/a")
@RestController
public class ArticleController {
@Resource
private ArticleService articleService;
@RequestMapping("/getall")
public List getAll() {
return articleService.getAll();
}
}
import com.example.demo.mapper.ArticleMapper;
import com.example.demo.model.ArticleInfo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class ArticleService {
@Resource
private ArticleMapper articleMapper;
public List getAll() {
return articleMapper.getAll();
}
}
import com.example.demo.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ArticleMapper {
List getAll();
}
一对多需要使用 标签,用法和 相同,如下所示:
insert into user(
username,
password,
nickname,
sex,
birthday,
head
) values (
#{username},
#{password},
#{nickname},
#{sex},
#{birthday},
#{head}
)
- prefix:表示整个语句块,以prefix的值作为前缀
- suffix:表示整个语句块,以suffix的值作为后缀
- prefixOverrides:表示整个语句块要去除掉的前缀
- suffixOverrides:表示整个语句块要去除掉的后缀
调整 UserMapper.xml 的插入语句为:
insert into user
username,
password,
nickname,
sex,
birthday,
head,
create_time,
#{username},
#{password},
#{nickname},
#{sex},
#{birthday},
#{head},
#{createTime},
List selectByCondition(User user);
以上标签也可以使用
int updateById(User user);
update user
username=#{username},
password=#{password},
nickname=#{nickname},
sex=#{sex},
birthday=#{birthday},
head=#{head},
create_time=#{createTime},
where id=#{id}
- collection:绑定方法参数中的集合,如 List,Set,Map或数组对象
- item:遍历时的每一个对象
- open:语句块开头的字符串
- close:语句块结束的字符串
- separator:每次遍历之间间隔的字符串
int deleteByIds(List ids);
delete from article
where id in
#{item}