1、mybatis框架概述
2、直接使用jdbc连接数据库带来的问题
3、mybatis连接池
3.1、mybatis连接池yml配置
3.2、mybatis连接池xml配置
4、一个简单的mybatis框架demo(XML配置)
4.1、maven项目目录结构如下:
4.2、代码
4.3、mybatis代码架构分析
5、一个简单的mybatis框架demo(annotation配置)
5.1、maven项目目录结构如下
5.2、mybatis注解使用
6、mybatis总结
7、参考资料
2022/7/27补充
文章中所涉及的代码源码下载地址:ssm-learning: ssm学习的demo代码相关博客:https://blog.csdn.net/weixin_42032770/article/details/112222474https://blog.csdn.net/weixin_42032770/article/details/112437956https://blog.csdn.net/weixin_42032770/
mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注sql 语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。 mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行sql 并将结果映射为 java 对象并返回。 采用ORM思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。 为了我们能够更好掌握框架运行的内部过程,并且有更好的体验,下面我们将从自定义 Mybatis 框架开始来 学习框架。此时我们将会体验框架从无到有的过程体验,也能够很好的综合前面阶段所学的基础。
(projo对象就是简单的java对象,可以理解为实体类与数据库中表一一映射的对象,可以参考java对象 POJO和JavaBean的区别_X丶L的博客-CSDN博客_javabean和pojo的区别)
连接池就是用于存储连接对象的一个容器。而容器就是一个集合,且必须是线程安全的,即两个线程不能拿到同一个连接对象。同时还要具备队列的特性:先进先出原则。
使用连接池的好处:避免频繁创建和关闭数据库连接造成的开销,节省系统资源。
server:
port: 8080
spring:
datasource:
name: erp
url: jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Hongkong
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml #注意:一定要对应mapper映射xml文件的所在路径
type-aliases-package: com.mybatis_demo.domain # 注意:对应实体类的路径jetbrains://idea/navigate/reference?project=DataBase_conn&fqn=com.example.demo.Entity
建立一个maven工程
eclipse配置maven可参考 Eclipse配置Maven详细教程_Bird鸟人的博客-CSDN博客_eclipse maven
eclipse建立maven工程可参考 https://jingyan.baidu.com/article/2fb0ba40a2b22b00f2ec5faf.html
IUserDao.java
package com.mybatis_demo.dao;
import com.mybatis_demo.domain.User;
import java.util.List;
/**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:13
*/
public interface IUserDao {
/**
*查询所有
* @return
*/
List findAll();
/**
* 根据id查询
* @param id
* @return
*/
List findByUid(Integer uid);
/**
* 根据name模糊查询
* @param userName
* @return
*/
List findByName(String userName);
/**
* 根据id删除
* @param id
* @return
*/
int deleteUser(Integer uid);
/**
* 添加
* @param user
* @return
*/
int saveUser(User user);
/**
* 修改
* @param user
* @return
*/
int updateUser(User user);
}
User.java
package com.mybatis_demo.domain;
import java.io.Serializable;
import java.sql.Date;
/**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:08
*/
public class User implements Serializable {
private Integer uid;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
public User() {
}
public User(Integer uid, String userName, Date userBirthday, String userSex, String userAddress) {
this.uid = uid;
this.userName = userName;
this.userBirthday = userBirthday;
this.userSex = userSex;
this.userAddress = userAddress;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getUserBirthday() {
return userBirthday;
}
public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", userName='" + userName + '\'' +
", userBirthday=" + userBirthday +
", userSex='" + userSex + '\'' +
", userAddress='" + userAddress + '\'' +
'}';
}
}
IUserDao.xml
insert into
user(id,username,address,sex,birthday)values(#{uid},#{userName},#{userAddress},#{userSex},#{userBirthday})
delete from user where id=#{uid}
update user set username=#{userName},address=#{userAddress},sex=#{userSex},birthday=#{userBirthday} where id=#{uid}
IUserDao.xml中的映射配置需要注意!!!
jdbcConfig.properties
jdbc.driver=com.mysql.jdbc.Driver
#mysql5.7以下版本,则可以直接这样写
#jdbc.url=jdbc:mysql://localhost:3306/ssm
#注意url这里,如果是mysql5.7及以上的要在后面设置useUnicode=true&characterEncoding=UTF-8
#否则会出现中文显示?
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
SqlMapConfig.xml
MybatisTest.java
package com.mybatis_demo.test;
import com.mybatis_demo.dao.IUserDao;
import com.mybatis_demo.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
/**
* @description:
* @author: wu linchun
* @time: 2020/12/30 22:25
*/
public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private IUserDao userDao;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@Before//用于在测试方法执行之前执行
public void init() throws Exception {
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
sqlSession = factory.openSession();
//4.获取dao的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}
@After//用于在测试方法执行之后执行
public void destroy() throws Exception {
//提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
}
/**
* 测试查询所有
*/
@Test
public void testFindAll(){
List userList = userDao.findAll();
for(User user : userList){
System.out.println(user);
}
}
/**
* 测试添加用户
* @throws ParseException
*/
@Test
public void testSaveUser() throws ParseException {
java.util.Date bir=sdf.parse("2020-01-04");
java.sql.Date bir_sql=new java.sql.Date(bir.getTime());
User user=new User(11,"test11", bir_sql,"男","testAddress");
userDao.saveUser(user);
}
/**
* 测试删除用户
*/
@Test
public void testDeleteUser(){
userDao.deleteUser(7);
}
/**
* 测试根据uid查找
*/
@Test
public void testFindByUid(){
List userList = userDao.findByUid(6);
for(User user : userList){
System.out.println(user);
}
}
/**
* 测试根据userName模糊查询
*/
@Test
public void testFindByName(){
List userList=userDao.findByName("%t%");
for(User user : userList){
System.out.println(user);
}
}
/**
* 测试修改
* @throws ParseException
*/
@Test
public void testUpdateUser() throws ParseException {
java.util.Date bir=sdf.parse("2020-01-04");
java.sql.Date bir_sql=new java.sql.Date(bir.getTime());
User user=new User(5,"test5",bir_sql,"男","testAddress");
userDao.updateUser(user);
}
/**
* 入门案例
* @param args
*/
/*public static void main(String[] args) throws Exception {
//1.读取配置文件D:\学习资料\后端\ssm代码\mybatis_demo\src\main\resources\SqlMapConfig.xml
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}*/
}
IUserDao.java
package com.mybatis_demo_ann.dao;
import com.mybatis_demo_ann.domain.User;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import java.util.List;
/**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:08
*/
public interface IUserDao {
/**
* 查询所有操作
*
* @return
*/
@Select("select * from user")
//映射转换,将实体类中的字段与数据库表的列名一一对应起来
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
List findAll();
/**
* 插入操作
* @param user
* @return
*/
@Insert("insert into user (id,username,birthday,sex,address) values (#{uid},#{userName},#{userBirthday},#{userSex},#{userAddress})")
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
int saveUser(User user);
/**
* 更新操作
* @param user
* @return
*/
@Update("update user set username=#{userName},birthday=#{userBirthday},sex=#{userSex},address=#{userAddress} where id=#{uid}")
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
int updateUser(User user);
/**
* 模糊查询
* @param username
* @return
*/
@Select("select * from user where username like #{username}")
List findByName(String username);
/**
* 删除用户
* @param id
* @return
*/
@Delete("delete from user where id=#{id}")
int deleteUser(int id);
}
注意!!!使用注解开发时,要求实体类数据中属性必须和 mysql 中的属性名一致(除非你进行映射转换的配置),可以忽略大小写。
可参考文章:https://blog.csdn.net/guan_sir/article/details/104561362 MyBatis中的@results注解使用_Evan@DL&&java的博客-CSDN博客_mybatis result注解
mybatis中mapper xml中写select xxx from TTT where a in (...)
mapper层
List listTeamSalaryHistoryInfos(@Param("teamIds") String[] teamIds,
@Param("beginDate") String beginDate,
@Param("endDate") String endDate);
xml
参考资料
mybatis同时传入List/数组和实体类参数_withwindluo的博客-CSDN博客