前言 这个学期学校开始教javaee框架,虽说我之前已经稍微学习了解过ssm,但学习的过程以及内容挺碎片化的。现在再按学校教程顺序重新过一遍理论。从这篇博文开始记录一下学习ssm的整个过程。
mybatis简介 之前没有使用mybatis时通常都是使用jdbc的方法(主要的操作对象:Connection、Preparestatement、ResultSet)来操作数据库,每次执行sql操作都要频繁建立数据库连接,从而造成资源的浪费。mybatis是一种ORM框架,ORM框架可以完成对象模型和关系模型的映射。采用ORM框架后,应用程序不用再直接访问数据库,而是以面向对象的方法来操作持久化对象(PO),其通过面向对象的方法来代替程序操作底层SQL。简单理解就是mybatis不用执行jdbc方法中过多繁琐的操作,可以简化数据库操作。
mybatis的配置
如果在springboot项目中,只需在springboot整体的配置文件application.yml中配置即可
spring: datasource: username: 账号 password: 密码 url: jdbc:mysql://localhost:3306/数据库名?useSSL=false&serverTimezone=GMT driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:映射文件目录mapping所在(如:classpath:mapping/*Mapper.xml) type-aliases-package: 数据库映射实体对象别名包(如:per.study.entity)
如果在其他项目中,则要额外编写配置文件(.xml),下面是一个简单的mybatis配置文件范例
<?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 > <environments default ="mybatis" > <environment id ="mybatis" > <transactionManager type ="JDBC" > </transactionManager > <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/test-mybatis?useSSL=false& serverTimezone=GMT& characterEncoding=utf8" /> <property name ="username" value ="root" /> <property name ="password" value ="root" /> </dataSource > </environment > </environments > <mappers > <mapper class ="mapper.BookMapper" > </mapper > </mappers > </configuration >
mapper的使用 由于已经配置好配置文件,则我们可以开始关注具体业务的实现,不用再关心数据库连接的问题。
mapper即是映射文件,通常命名为 实体名+Mapper.xml。mapper文件是sql语句的具体实现,增删改查的sql语句都会写在mapper里(非注解方式)。而对应的在程序里的接口类可以在mapper文件里指明来使用。
现在举个映射文件方式使用mapper的例子。(数据库all_comic表与Comic实体对应)
首先建个实体类Comic
@Data public class Comic { private Integer comicId; private String comicName; private String comicDescription; private String comicCover; private Date createTime; private Date updateTime; }
其对应的接口dao层
public interface ComicMapper { List<Comic> queryAll () ; }
接口所对应的mapper,mapper标签的namespace要指定接口文件的位置,resultMap是定义返回的结果集,增删改查的语句就不用多说了
<?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.kbcomic.mapper.ComicMapper" > <resultMap id ="comic" type ="com.example.kbcomic.entity.Comic" > <result column ="comic_id" property ="comicId" > </result > <result column ="comic_name" property ="comicName" > </result > <result column ="comic_description" property ="comicDescription" > </result > <result column ="comic_cover" property ="comicCover" > </result > <result column ="create_time" property ="createTime" > </result > <result column ="update_time" property ="updateTime" > </result > </resultMap > <select id ="queryAll" resultMap ="comic" > select * from all_comic </select > </mapper >
根据上面mapper文件和mapper接口的映射,我们直接通过对象调用接口即可实现数据库操作
InputStream inputStream= Resources.getResourceAsStream("mybatis-config.xml" ); SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream); SqlSession sqlSession = factory.openSession(); ComicMapper mapper = sqlSession.getMapper(ComicMapper.class); List<Comic> comics = mapper.queryAll(); for (Comic comic:comics){ System.out.println(comic); }
注解方式实现mapper
public interface ComicMapper { @Select("select * from all_comic") @Results(id = "comic",value = { @Result(id = true,column = "comic_id",property = "comicId"), @Result(column = "comic_name",property = "comicName"), @Result(column = "comic_description",property = "comicDescription"), @Result(column = "comic_cover",property = "comicCover"), @Result(column = "create_time",property = "createTime"), @Result(column = "update_time", property="updateTime") }) List<Comic> queryAll () ; }
由此可见使用注解方式不用再编写mapper.xml文件,更进一步简化整个流程。这也是通常大众所使用的方式。
mybatis中的缓存机制 mybatis缓存分为一级缓存和二级缓存,同时也可以配置关于缓存的设置。一级缓存是位于SqlSession上的缓存,二级缓存是在SqlSessionFactory上的缓存。通常情况下,mybatis会开启一级缓存,也就是处于SqlSession上的缓存,这个缓存不需要POJO对象可序列化。
二级缓存的开启
在mybatis的配置文件中的settings标签中添加二级缓存的开启
<configuration > <settings > <setting name ="cacheEnabled" value ="true" /> </settings > </configuration >
(非注解方式)在mapper中添加二级缓存声明
<?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.kbcomic.mapper.ComicMapper" > <cache > </cache > <resultMap id ="comic" type ="com.example.kbcomic.entity.Comic" > <result column ="comic_id" property ="comicId" > </result > <result column ="comic_name" property ="comicName" > </result > <result column ="comic_description" property ="comicDescription" > </result > <result column ="comic_cover" property ="comicCover" > </result > <result column ="create_time" property ="createTime" > </result > <result column ="update_time" property ="updateTime" > </result > </resultMap > <select id ="queryAll" resultMap ="comic" > select * from all_comic </select > </mapper >
(注解方式)添加二级缓存,在mapper接口上添加@CacheNamespace(blocking = true)或对应方法添加option注解
@CacheNamespace(blocking = true) public interface ComicMapper { @Select("select * from all_comic") @Results(id = "comic",value = { @Result(id = true,column = "comic_id",property = "comicId"), @Result(column = "comic_name",property = "comicName"), @Result(column = "comic_description",property = "comicDescription"), @Result(column = "comic_cover",property = "comicCover"), @Result(column = "create_time",property = "createTime"), @Result(column = "update_time", property="updateTime") }) @Options(useCache = true) List<Comic> queryAll () ; }
缓存方式的利弊
利:开启缓存后,第一次查询会执行sql,第二次及以后的查询都会从缓存中读取数据。减少了访问数据库的次数,优化系统性能。 弊:开启缓存的弊端是数据没有实时性,当数据库中的数据一旦修改,查询的数据还是缓存中的数据没有实时性。
对于缓存方式的弊端,有如下解决方案
(非注解方式) ①禁止缓存:在mapper文件select语句中设置useCache=”false”
<select id ="queryAll" resultMap ="comic" useCache ="false" > select * from all_comic </select >
②清空缓存:在insert或update语句中设置flushCache=”true”
<update id ="updateComic" flushCache ="true" > update all_comic set comic_description=#{comic.comicDescription},comic_cover=#{comic.comicCover},update_time=#{comic.updateTime} where comic_id=#{comicId} </update >
(注解方式)
@Options(flushCache = Options.FlushCachePolicy.TRUE) Integer updateComic (Comic comic) ;@Options(useCache = false) List<Book>queryAll();