本文将利用一个简单的登录评论功能,完整介绍mybatis框架的使用。
实现功能:对数据库的增删改查,多表查询,模糊查询,动态查询
本文使用环境/工具:
数据库:mysql 5.7
JDK:8
IDEA:2020.1
数据库可视化工具:Navicat(破解版已经上传至这个项目的github里面,需要的可以下载)
本文所有代码已经上传至github里面
https://github.com/index9-44/Mybatis
觉得还不错能不能给我点个star
MyBatis(前身是iBatis)是一个支持普通SQL查询、存储过程以及高级映射的持久层框架。
MyBatis框架也被称之为ORM(Object/Relation Mapping,即对象关系映射)框架。所谓的ORM就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术,它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。
1.基于SQL语法,简单易学。
2.能了解底层组装过程。
3.SQL语句封装在配置文件中,便于统一管理与维护,降低了程序的耦合度。
4.程序调试方便。
5.减少了61%的代码量
6.最简单的持久化框架
7.架构级性能增强
8.SQL代码从程序代码中彻底分离,可重用
9.增强了项目中的分工
10.增强了移植性
MyBatis特点就先介绍到这里,下面我们手把手教你如何使用MyBatis来搭建一个用户登录注册系统(含增删改查)
我们先打开Navicat创建一个mybatis数据库,再创建一个user表设置主键uuid自动从1000开始递增,设置如下:
这里自增从100开始只是我设置的,你想从1,1000,10000000开始都没问题的。
全部字段如下
打开IDEA,需要设置如下内容,勾选右侧那些功能。
如果不会,可以创建一个简单的javaweb程序,然后在pom.xml里面导入如下依赖,上面的项目建设完毕,还需要检查一下是否导入下面最上面那三个依赖
com.alibaba
druid-spring-boot-starter
1.1.14
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.2
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-devtools
runtime
true
org.springframework.boot
spring-boot-configuration-processor
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
application.properties配置文件如下,由于我用的是thymeleaf模板,所以有上面的代码,如果你不想用模板,可以删掉。
MySQL数据库连接配置需要根据你自己的数据库修改,比如数据库登录密码你需要修改,如果数据库名字跟我不一样,第一行的mybayis也需要修改为你的数据库名字
#模板缓存:开启
spring.thymeleaf.cache=false
#模板编码
spring.thymeleaf.encoding=UTF-8
#模板样式
spring.thymeleaf.mode=HTML5
#指定模板页面存放路径
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
# MySQL数据库连接配置
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
spring.datasource.username=root
spring.datasource.password=123123
#添加并配置第三方数据源druid
spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=20
spring.datasource.minIdle=10
spring.datasource.maxActive=100
#配置MyBatis的xml配置文件路径
mybatis.mapper-locations=classpath:mapper/*.xml
#配置XML映射文件中指定的实体类别名路径
mybatis.type-aliases-package=com.mybatis.demo.domain
#开启驼峰命名匹配映射
mybatis.configuration.map-underscore-to-camel-case=true
这时候一个简单的Mybatis前期准备工作就完成了
springboot老套路,来个控制层,当用户在浏览器输入/login的时候,跳转至登录界面。
比较基础的springboot配置跳转设置的我就不演示了,毕竟跟我主题有一点偏了
@Controller
@RequestMapping("/")
public class loginController {
@GetMapping("/login")
public String toLogin(){
return "login";
}
}
既然到这里可以进入登录界面了,那就要解决从页面拿值到控制层,去控制层与数据库交互判断是否有这个用户,请继续下面步骤完成操作
如下图所示创建用户类(user),我们这里要根据我们数据库user表来分别创建对应的属性,名字可以不相同(后面我们来解决名字不同,但是可以对应属性)
代码如下
import lombok.Data;
import java.util.Date;
//@Data注解:记得装lombok插件和去pom.xml导入lombok依赖
@Data
public class user {
private Long id; //用户UUID
private String username; //用户账号
private String password; //用户密码
private Date createTime; //账号创建时间
private String registerIp; //注册ip地址
private int role; //用户性别
}
既然用户类都创建了,我们这时候就要写对应的接口,完成对数据库的操作
我们这里使用@Select注解的方式,完成查询操作。如果你入门过sql,肯定猜的出来
@Insert(…) 是插入操作 @Delete(…)删除操作 @Update(…)更新操作
代码如下图所示
@Param(“username”),@Param(“password”)用来分别获取页面的账号和密码,双引号里面的参数自然就是前端页面input输入框里面的name
import com.zsc.mybatis.demo.domain.user;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
//一定要加mapper注解,那不然会扫描不到这个接口
@Mapper
public interface userMapper {
@Select("select * from user as u where u.username=#{username} and u.password=#{password}")
//@Param("username"),@Param("password")用来分别获取页面的账号和密码
public List getUser(@Param("username")String username ,@Param("password") String password);
}
这里就是前端页面,很清楚的看到name里面分别对应的内容
到这里既然实体类也创建了,mapper接口也写好了,那肯定来控制层测试一下我们写的对不对了
代码如下:
//注入 如果userMapper有报错,可以忽略,其实是对的
@Autowired
userMapper userMapper;
//我们这里就不搞花里胡哨的了,来返回一个简单的josn
@ResponseBody
@PostMapping("/login")
public String dellogin(String username,String password){
try {
List list=userMapper.getUser(username,password);
if (list.size()==0)
return "登录失败查无此用户";
else
System.out.println(list);
return "登录成功";
}catch (Exception e){
System.out.println(e.toString());
}
return "登录失败,请检查错误";
}
至此代码已经写完了,我们去测试一下,我数据库里面有一条数据
我们去页面测试
登录失败:
登录成功
查到的数据:
我们肯定会有疑问,为啥user实体类里面的属性与数据库里面的字段并不相等,可是为啥依然会获取到数据呢?
原因很简单,我们在前面配置的时候,设置了驼峰命名匹配映射
#开启驼峰命名匹配映射
mybatis.configuration.map-underscore-to-camel-case=true
至此已经完成了对数据库的查询操作,下面为了加快学习,我们直接使用测试类完成剩余的增删改
创建完毕后,就要开始在如下目录创建userMapper.xml文件,开始编写配置文件
namespace表示命名空间,一定要对应的Mapper下面,不会的可以仿照我的来写。下面就是所有的增删改查操作代码
insert into user(username,password,create_time,register_ip,role)
value (#{user.username},#{user.password},#{user.createTime},#{user.registerIp},#{user.role})
delete from user where username=#{username} and password=#{password}
update user set username=#{user.username},password=#{user.password},create_time=#{user.createTime},
register_ip=#{user.registerIp},role=#{user.role} where uuid=#{user.uuid}
这里很简单的就能看出来我们这里的sql语句的注解已经没有了,因为会在后面
@Mapper
public interface userMapper {
//基于配置文件完成查询操作
//查询用户操作
public List getUser(@Param("username")String username ,@Param("password") String password);
//增加用户操作
public void plususer(@Param("user")user user);
//删除
public void deluser(@Param("username")String username,@Param("password") String password);
//修改操作
public void updateuser(@Param("user") user user);
}
如下跟我在控制层的写法基本一致
@SpringBootTest
@RunWith(SpringRunner.class)
public class userMapperTest {
//注入
@Autowired
userMapper userMapper;
//查询操作
@Test
public void getUser(){
List list=userMapper.getUser("admin","123");
System.out.println(list);
}
//插入操作
@Test
public void plususer(){
Date date=new Date();
user user=new user();
user.setUsername("谁都不许动我的砖");
user.setPassword("辣鸡一个");
// user.setRegisterIp(request.getRemoteHost()); 此句可以获取注册ip地址
user.setCreateTime(date);
user.setRegisterIp("0.0.0.0");
user.setRole(1);
System.out.println(user.toString());
userMapper.plususer(user);
System.out.println(user.toString());
}
//删除测试
@Test
public void deluser(){
userMapper.deluser("李四","456");
}
//更新测试
@Test
public void uodateuser(){
//获取当前username=“蔡徐坤”,password="985"的用户
user user=new user();
List list;
list=userMapper.getUser("蔡徐坤","985");
//获取完后赋值给user
user=list.get(0);
user.setUsername("蔡徐坤好帅");
user.setPassword("真的吗?");
//下面就不再修改了,根据自己需要修改对应的属性
userMapper.updateuser(user);
}
所以测试结果如下:
成功执行查询数据操作
成功执行插入操作
细心的同学肯定能看出来,为什么插入操作以后uuid就不是null呢?因为我们看前面插入的配置文件代码
//useGeneratedKeys="true" keyProperty="uuid" 这里就是代表执行插入操作后,返回uuid,所以我们可以看到在插入操作后返回uuid
成功执行删除操作
成功执行修改操作
因为先是一次查询再是一次修改操作,所以有两次sql语句执行
这里我们实际演示一个常见用户评论的操作
说明:因为用户与评论是一对多的关系,并且,用户在评论里面还会附带一些附件(文件)或者图片,所以我们在获取用户评论内容的同时,将其关联的用户对象和附件也获取,则可以参照我下面的方式实现。
ER图如下:
评论类
评论数据库:
文件类,file就是评论下面上传的文件图片之类的
这里依然是上面的老套路,编写接口,然后对应的sql语句都在下面完成。看到这里,接口函数就不放出来了,可以看我下面sql语句里面的id轻松写出来,快去试一试吧。
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ecec90d] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27d33393] will not be managed by Spring
==> Preparing: select * from comment where comment_id=?
==> Parameters: 1000(Long)
<== Columns: comment_id, uuid, comment, create_time
<== Row: 1000, 101, 谁都不许动我的砖, 2020-05-12 11:11:32
====> Preparing: select * from user where uuid=?
====> Parameters: 101(Long)
<==== Columns: uuid, username, password, create_time, register_ip, role
<==== Row: 101, 张三, 123, null, 192.168.1.1, 1
<==== Total: 1
====> Preparing: select * from file where comment_id=?
====> Parameters: 1000(Long)
<==== Columns: file_id, file, comment_id
<==== Row: 1000, 砖1, 1000
<==== Row: 1001, 砖2, 1000
<==== Row: 1002, 砖3, 1000
<==== Row: 1005, csdn, 1000
<==== Total: 4
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ecec90d]
[comment(commentId=1000, uuid=null, comment=谁都不许动我的砖, createTime=Tue May 12 19:11:32 CST 2020, fileList=[file(fileId=1000, file=砖1, commentId=1000), file(fileId=1001, file=砖2, commentId=1000), file(fileId=1002, file=砖3, commentId=1000), file(fileId=1005, file=csdn, commentId=1000)], user=user(uuid=101, username=张三, password=123, createTime=null, registerIp=192.168.1.1, role=1))]
我数据库的数据:
看下图,可以看出查询结果是没问题的
所以实现了对数据库的多表查询,实现一对多、多对多的对象关联
注意:为了避免关联对象立即加载问题,可以在配置文件中使用懒加载的方式。懒加载只在加载对象时不会立即加载该对象的关联对象,而只有在调用如get()等方法才会进行加载。懒加载时性能优化的一种方式。
懒加载配置如下:
所以建议把前面的application.properties内容改为 application.yml,内容就是下面的内容
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
username: root
password: 123
driver-class-name: com.mysql.cj.jdbc.Driver
#配置Mybatis的相关属性
mybatis:
mapper-locations: classpath:com.zsc.ticketsys.mapper/*.xml #指定mapper XML文件的位置
type-aliases-package: com.zsc.ticketsys.domain #指定实体类的别名的映射路径
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印输出SQL语句
map-underscore-to-camel-case: true # 启动驼峰式转换
use-generated-keys: true #开启自增组件
lazy-loading-enable:true #启动懒加载
aggressive-lazy-loading:false #禁用立即加载
依然是上面老套路,编写mapper接口,编写xml配置文件,再用测试类完成测试,直接放代码
commentMapper.xml
commentMapper.java
//模糊查询
public List listLikeComment(@Param("comment") String comment);
测试类commentMapperTest.java的编写
@Test
public void listLikeComment(){
List commentsList=commentMapper.listLikeComment("就");
System.out.println(commentsList);
}
基本语句如下,我就不再做测试了,大体意思就是查询ticket表,如果字段subject和type不为空,那么就模糊查询subject并且指定内容的type
1.我已经把数据的信息贴到了文章里,可以自行搭建数据表,源码在上面连接里面,可以下载
2.application.properties去这个文件夹下面修改为您的数据库信息
3.那个Navicat压缩包解压至您的硬盘,双击图标即可使用不需要破解!!
以上内容就是mybatis框架主要内容,如果您觉得写的不错能不能给小的我点个赞或者点个收藏。