Mybatis
介绍
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
下面带你动手用mybatis 注解方式写一个简单的增删改查
注解开发案例
mybatis注解开发适用于一些简单的系统,数据库系统不复杂的系统使用注解开发效率会高很多,但对于一些复杂的数据库系统或者一些复杂的要求,这时候使用注解开发可能就没有办法完成了。
目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 E:. ├─.idea │ ├─artifacts ├─.mvn │ └─wrapper └─src ├─main │ ├─java │ │ └─com │ │ ├─Entity │ │ ├─Mapper │ │ ├─Service │ │ └─utils │ ├─resources │ └─webapp │ └─WEB-INF └─test ├─java │ └─com │ └─Service └─resources
结构分析:
Entity:数据库对应的实体类
Mapper:注解实现映射器
Service:获取Mapper实现数据处理
utils:工具包
添加mybatis依赖
在pom.xml引入以下依赖,我这里使用mybatis 3.5.3版本,你也可以使用其他版本,数据库我使用的5.1.49版本。
引入内容后,加载依赖。右键—>maven—>重新加载项目
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.3</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.49</version > </dependency >
添加mybatis配置文件
在resources下有两个文件,mybatis-config.xml是配置mybatis一些相关配置,db.properties是配置连接数据库的。
添加一个名为mybatis-config的xml格式文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <properties resource ="db.properties" /> <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> </settings > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" > </transactionManager > <dataSource type ="POOLED" > <property name ="driver" value ="${driver}" /> <property name ="url" value ="${url}" /> <property name ="username" value ="${username}" /> <property name ="password" value ="${password}" /> </dataSource > </environment > </environments > <mappers > <package name ="com.mapper" /> </mappers > </configuration >
新建一个资源文件db.properties,内容如下:
1 2 3 4 driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf-8 username=root password=root
根据你自己的情况修改,数据库一般默认是3306端口,如果你可以修改过,那只需要修改username和password就好。
导入数据库
导入数据库是这样的,如图:
新建实体类
在com包下新建一个名为entity包,在entity包下新建一个类名为Personal的实体类。
每一个属性都有对应数据库的字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package com.Entity;public class Personal { Integer id; String name; String height; Integer age; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public String getHeight () { return height; } public void setHeight (String height) { this .height = height; } public Integer getAge () { return age; } public void setAge (Integer age) { this .age = age; } }
新建一个utils包
在com包下新建一个utils包,在utils包下新建一个名为SqlSessionFactoryUtils
的类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.utils;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;import java.io.InputStream;public class SqlSessionFactoryUtils { private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml" ; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder ().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSessionFactory getSqlSessionFactory () { return sqlSessionFactory; } }
编写接口
在com包下新建一个mapper包,在mapper包下新建一个PersonalMapper接口,我们需要写SQL语句时,在这接口写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package com.Mapper;import com.Entity.Personal;import com.Service.PersonalService;import org.apache.ibatis.annotations.*;import java.util.List;public interface PersonalMapper { @Select("select * from personal") List<Personal> findAll () ; @Insert("insert into personal (id,name,height,age) value(#{id},#{name},#{height},#{age})") int addPersonal (Personal personal) ; @Delete("delete from personal where id =#{id}") int delPersonalById (@Param("id") Integer id) ; @Update("update personal set name = #{name} where id = #{id}") int updatePersonalById (@Param("name") String name, @Param("id") Integer id) ; }
数据库操作实例
SQL语句写好了,就可以开始写实例了,对数据库进行增删改查了,我们将这部分的代码放在com包下的service包中。
在com下新建一个service包,并在service包新建一个PersonalService类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 package com.service;import com.entity.Personal;import com.mapper.PersonalMapper;import com.utils.SqlSessionFactoryUtils;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import java.util.List;public class PersonalService { SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory(); public List<Personal> selectAll () { SqlSession sqlSession = factory.openSession(); PersonalMapper mapper = sqlSession.getMapper(PersonalMapper.class); List<Personal> personals = mapper.findAll(); sqlSession.close(); return personals; } public int addPersonal (Personal personal) { SqlSession sqlSession = factory.openSession(); PersonalMapper mapper = sqlSession.getMapper(PersonalMapper.class); int rows = mapper.addPersonal(personal); sqlSession.commit(); return rows; } public int delPersonal (Integer id) { SqlSession sqlSession = factory.openSession(); PersonalMapper mapper = sqlSession.getMapper(PersonalMapper.class); int rows = mapper.delPersonalById(id); sqlSession.commit(); return rows; } public int updatePersonal (Integer id , String name) { SqlSession sqlSession = factory.openSession(); PersonalMapper mapper = sqlSession.getMapper(PersonalMapper.class); int rows = mapper.updatePersonalById(name,id); sqlSession.commit(); return rows; } }
测试实例
我们使用的是Junit5测试,在PersonalService类中,右键--->生成--->测试--->选择全部成员--->确定
。
生成测试后,在src/test/java/com.service/
下可以看到这一个类PersonalServiceTest
。
复制以下已经写好的测试内容到你的类PersonalServiceTest
中。
不会使用测试?
在测试类中,有很多个方法,方法名左边有个绿色的三角形,点击三角形就是开始测试,测试是否正常,看左下方的终端是绿色还是红色,绿色代表测试通过,红色代表测试不通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.service;import com.entity.Personal;import org.junit.jupiter.api.Test;import java.util.List;class PersonalServiceTest { PersonalService personalService = new PersonalService (); @Test void selectAll () { List<Personal> personals= personalService.selectAll(); System.out.println("-----------------" ); for (Personal personal : personals) { System.out.println("个人信息:" +personal.getName()); } System.out.println("-----------------" ); } @Test void addPersonal () { Personal personal = new Personal (); personal.setId(7 ); personal.setAge(19 ); personal.setHeight("178" ); personal.setName("小码博客" ); int rows = personalService.addPersonal(personal); System.out.println("受影响行数为:" +rows); } @Test void delPersonal () { int rows = personalService.delPersonal(5 ); System.out.println("受影响行数为:" +rows); } @Test void updatePersonal () { int rows = personalService.updatePersonal(2 ,"blog.hikki.site" ); System.out.println("受影响行数为:" +rows); } }
测试结果如下说明项目没有问题了,可以正常使用。

XMl映射器开发案例
这次使用XML映射器开发,不使用注解了。
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。
项目使用方法
项目结构分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ├─java │ └─com │ ├─entity │ │ Article.java │ │ Tag.java │ │ User.java │ │ │ ├─mapper │ │ ArticleDao.java │ │ ArticleMapper.xml │ │ UserDao.java │ │ UserMapper.xml │ │ │ └─utils │ MybatisUtils.java │ Othor.java │ ├─resources │ db.properties │ log4j.properties │ mybatis-config.xml │ └─webapp │ index.jsp │ └─WEB-INF web.xml
连接数据库
将项目根目录discuss.sql文件导入你的数据库
默认数据库连接用户:root
默认数据库连接密码:root
根据你自己的情况修改用户名和密码
加载依赖
打开根目录的pom.xml文件,右键—>Maven—>重新加载项目
Junit测试项目
打开根目录下的src/test/java/com/mapper/ArticleDaoTest类
点击类名左边的绿色三角符号开始测试该类,查看下方的终端,全是绿色,没有看见红色,则说明测试结果通过,该项目可以正常运行
配置文件
使用XML映射器开发也要设置配置文件
1 2 3 4 ├─resources │ db.properties │ log4j.properties │ mybatis-config.xml
数据库连接配置db.properties:
我这里使用mariadb
数据库,mariadb
数据库的用法和mysql
几乎一样,如果你没有安装mariadb
,可以试着去安装一下,或者你直接将数据库文件导入mysql也是一样的,但可能需要改动一下文件内容。
1 2 3 4 driver=org.mariadb.jdbc.Driver url=jdbc:mariadb://localhost:3307/discuss?useUnicode=true&characterEncoding=utf-8 username=root password=root
mybatis配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <properties resource ="db.properties" /> <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> <setting name ="lazyLoadingEnabled" value ="true" /> <setting name ="aggressiveLazyLoading" value ="false" /> </settings > <typeAliases > <typeAlias type ="com.entity.Article" alias ="Article" /> <typeAlias type ="com.entity.Tag" alias ="Tag" /> <typeAlias type ="com.entity.User" alias ="User" /> </typeAliases > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${driver}" /> <property name ="url" value ="${url}" /> <property name ="username" value ="${username}" /> <property name ="password" value ="${password}" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="com/mapper/ArticleMapper.xml" /> <mapper resource ="com/mapper/UserMapper.xml" /> </mappers > </configuration >
如果你的数据库有下划线"_"的话,你需要开启驼峰命名转换成大写,否则无法存储如实体类,
开启驼峰命名
1 2 3 4 <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> </settings >
新建实体类
数据库的每一张表一般都有一个实体类对应,根据数据库,我们新建三个实体类Article
、Tag
、User
,并且在每一个实体类添加数据表的字段属性,设置该属性为私有,并且生成get/set方法和toString方法。
比如Tag实体类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.entity;public class Tag { private String id; private String tag; @Override public String toString () { return "Tag{" + "id='" + id + '\'' + ", tag='" + tag + '\'' + '}' ; } public String getId () { return id; } public void setId (String id) { this .id = id; } public String getTag () { return tag; } public void setTag (String tag) { this .tag = tag; } }
新建mybatis工具类
每一个mybatis的应用都是基于SqlSessionFactory 的实例为核心的,SqlSessionFactory 的实例可以通过SqlSessionFactoryBuilder获得,而SqlSessionFactoryBuilder则可以通过mybatis的配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
使用mybatis文件构建SqlSessionFactory 的实例很简单,直接使用Resources.getResourceAsReader()即可,默认读取的路径是/src/main/resources/
下的文件。
1 2 3 4 Reader reader = Resources.getResourceAsReader("mybatis-config.xml" );sqlSessionFactory = new SqlSessionFactoryBuilder ().build(reader);
完整的获取SqlSessionFactory 实例的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.utils;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 java.io.Reader;public class MybatisUtils { public static SqlSessionFactory sqlSessionFactory = null ; static { try { Reader reader = Resources.getResourceAsReader("mybatis-config.xml" ); sqlSessionFactory = new SqlSessionFactoryBuilder ().build(reader); } catch (Exception e) { e.printStackTrace(); } } public static SqlSession getSession () { return sqlSessionFactory.openSession(); } }
新建Mapper
我们写的SQL语句存放在一个XML文件内,这个文件我们可以叫他为映射器。
XML的使用格式类似HTML,有单标签和双标签,比如我查询一个tb_article表的数据条数,使用<select></select>
括住SQL语句。其中在每一个SQL语句都有一个id
属性,这个属性就是为了从众多的SQL定位到某一条语句,resultType
属性是表示结果返回类型。
1 2 3 4 <select id ="getCount" resultType ="int" > select count(*) from tb_article </select >
常见的属性
id
:(必选)在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType
:(可选)参数传入的类型
resultType:
(可选)结果传出的参数类型,该属性和resultMap只能同时使用一个。
resultMap
:(可选)对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性, resultType 和 resultMap 之间只能同时使用一个。
增删改查
我们一般在实际应用上不使用删除标签,在表中定义一个状态,更改状态来达到删除数据。
每一段SQL语句都有一个id属性,至于是否有parameterType属性,根据自己的需求来是否添加,如果你需要在SQL语句中传入某参数,那就添加啊parameterType,不需要就不添加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <select id ="findArticleByAbbrlink" parameterType ="String" resultType ="Article" > select ta.id,ta.abbrlink,ta.title ,ta.context ,ta.create_time ,ta.wordcount ,ta.comment ,ta.number_reads ,tt.tag from tb_article ta inner join tb_tag tt on tt.id = ta.tag where ta.abbrlink = #{abbrlink} </select > <insert id ="addArticle" parameterType ="Article" > insert into tb_article (abbrlink,title,tag,context,create_time,user,wordcount,state) values (#{abbrlink},#{title},#{tag},#{context},#{create_time},"1",#{wordcount},#{state}) </insert > <update id ="updateArticleState" parameterType ="Article" > update tb_article set state =#{state} where abbrlink= #{abbrlink} </update >
动态SQL语句
我们可以根据Article实体类下的abbrlink、title、context属性值是否为空来进行对应的模糊查询,下面的标签表示只从标签下执行一个条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <select id ="findArticleAsURLAsTitleAsContext" parameterType ="Article" resultType ="Article" > select * from tb_article ta where 1=1 and <choose > <when test ="abbrlink!=null and abbrlink!=''" > ta.abbrlink like concat('%',#{abbrlink},'%') </when > <when test ="title!=null and title!=''" > ta.title like concat('%',#{title},'%') </when > <when test ="context!=null and context!=''" > ta.context like concat('%',#{context},'%') </when > </choose > </select >
我们还可以添加数组来遍历查询,比如,我们定义一个ArrayList
,里面存放的是abbrlink
的值,然后使用 <foreach>
标签进行遍历查询,结果集使用Article接收
1 2 3 4 5 6 7 <select id ="findArticleByAbbrlinks" parameterType ="List" resultType ="Article" > select * from tb_article where abbrlink in <foreach item ="abbrlink" index ="index" collection ="list" open ="(" separator ="," close =")" > #{abbrlink} </foreach > </select >
Mybatis-Plus
前言
Mybatis-Plus和Mybatis基本一样,开发步骤一样,下面我给出一个简单的案例来解释说明,不过,案例内容和上面不一样。
小技巧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override public void addArticle (ArticleDTO articleDTO) { System.out.println("debug--addArticle--articleDTO:" +articleDTO); List<Integer> tagIdList = tagService.addTag(articleDTO.getTagList()); Integer categoryId = categoryService.addCategory(articleDTO.getCategoryName()); Article article = BeanCopyUtil.copyBean(articleDTO, Article.class); article.setCategoryId(categoryId); article.setArticleCover("https://lsky.hikki.site/thumbnails/9e54d99bfd6587c219627297e0d7749b.png" ); articleMapper.insert(article); System.out.println("debug--addArticle--article.getID:" +article.getId()); }