mybatis笔记
官网地址:https://mybatis.org/mybatis-3/
使用mybatis进行crud
使用mybatis的第一步当然是导入依赖啦
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
通过xml配置 对于其他的配置可以查看官网 https://mybatis.org/mybatis-3/zh/configuration.html
<?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>
<!--连接数据库的环境,default="环境的id" environment 表示一个数据源 可以设置多个数据源-->
<environments default="a1">
<environment id="a1">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<environment id="a2">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
设置别名 也可以在实体类上通过注解设置 @Alias("别名")
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>
<!-- 指定maper文件的路径 只有指定了路径 mybatis才找到的这个mapper( maven项目从resources源文件夹下找资源)-->
<mappers>
<mapper resource="mybatisXML/StudentMapper.xml"/>
<mapper resource="mybatisXML/StudentMapper2.xml"/>
<mapper resource="mybatisXML/GradeMapper.xml"/>
<mapper resource="mybatisXML/RoleMapper.xml"/>
</mappers>
</configuration>
mybatis为我们提供了获取资源文件文件的 Resources类通过该类可以获取我们上面定义的xml文件用来修建 sqlSessionFactory 获取SqlSession ,SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。例如:
Reader resourceAsReader = Resources.getResourceAsReader("mapper.xml");
SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(resourceAsReader,"a2"); //指定数据源则采用默认的
SqlSession session = sqlSessionFactory.openSession();
有了sqlSession之后我们就可以来执行sql语句了 那么如何使用mybatis执行sql呢?
然后再resources文件下新建一个目录保存这些mapper,xml文件
<?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">
<--!-->namespace 是命名空间 标识mapper的唯一id 通过和dao的接口绑定</--!-->
<mapper namespace="com.sgp.dao.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
就可以通过SqlSession提供的方法来调用 com.sun.dao.BlogMapper客家可不加
List<Blog> list = session.selectList("com.sun.dao.BlogMapper.findAllStudent");
System.out.println(list);
也可以通过SqlSession 获得对应的mapper映射器直接调用mapper定义的方法
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog grade = mapper.selectBlog(1);
下面我们利用mybatis进行crud 首先在com.sun.dao.编写StudentDao
public interface StudentDao {
//增删改查的方法
public List<Student> getall();
public Student findById(int id);
public int insertStudent(Student student);
/**
* @return
*/
public Map find();
}
<?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">
<!--namespace="接口的完整路径"-->
<mapper namespace="com.sun.dao.StudentDao">
<!--id="方法名"-->
<select id="getall" resultType="com.sun.bean.Student">
select * from student
</select>
<select id="findById" parameterType="int" resultType="com.sun.bean.Student">
select * from student where studentid=#{id}
</select>
<!-- useGeneratedKeys="true"表示开启获取属性 keyProperty="studentid"表示吧主键id映射到实体studentId 上 获取到主键 适用于⾃增的主键列上-->
<insert id="insertStudent" parameterType="com.sun.bean.Student" useGeneratedKeys="true" keyProperty="studentId">
insert into student(studentno,stuname) values(#{studentNo},#{stuName})
</insert>
<select id="find" resultType="Map">
select max(studentid),min(studentid) from student
</select>
</mapper>
需要建立dao和xml的映射关系 有四种方式 在mybatis的配置文件中添加
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
接下来就可以创建SQLSession获取到mapper进行相关方法的调用了
可以看到 在mapper.xml里有这一些标签 对应这增删改查
每个标签都可以对应的属性
select
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
parameterMap | 用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。 |
resultType | 期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。 |
resultMap | 对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。 |
useCache | 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
fetchSize | 这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。 |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
resultOrdered | 这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false 。 |
resultSets | 这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。 |
Insert, Update, Delete 元素的属性
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
parameterMap | 用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅适用于 insert 和 update)指定主键的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset )。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
在上面mapper.xml可以看到一些“#{}” 这个是占位符 将当与jdbc的 “?” 是用来接收传递的参数的
还有一个"${}" 是直接替换 不会进行预处理 会注入
resultMap
resultMap是结果集映射 为我们省去了大量重复的 JDBC ResultSets
实现 对于简单的数据可以直接封装为 实体类对象 通过resultType属性指定 可以是 实体类 比如 User(int id,String username,String password)
<select id="selectUsers" resultType="map">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
如果对于User实体来说 存在某些字段和数据库不一样则不能正确的返回 可以通过起别名的方式解决
<select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
</select>
以上我们并没有显式的配置resultMap 因为mybatis已经为我们配置好了这种简单的,复杂的需要我们自己配 即可
需要注意
在select标签中resultType 设置的结果集属性是单表或者基础数据类型及其包装类
resultMap 设置的是 我们自定义的resultMap
<resultMap id="userResultMap" type="User">
主键需要用 <id>标识 property 是实体类属性名 column是数据库表属性
<id property="id" column="user_id" />
非主键简单属性使用 result标签
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
对于特复杂的比如说在我们的User实体类中 存在老师属性 而老师属性也是一个实体类进行多表联查的时候
<!-- 非常复杂的结果映射 -->
<resultMap id="userResultMap" type="User">
主键需要用 <id>标识 property 是实体类属性名 column是数据库表属性
<id property="id" column="user_id" />
非主键简单属性使用 result标签
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
association对应的是一对一 一个学生对应一个老师
<association property="teacher" javaType="com.sun.bean.Teacher">
<id column="s_id" property="gid"></id>
<result column="name" property="gname"></result>
</association>
如果是一对多关系 即结果是一个集合
<collection property="teacherlist" ofType="com.sun.bean.Teacher">
<id column="s_id" property="gid"></id>
<result column="name" property="gname"></result>
</collection>
</resultMap>
我们可以这样在关联association或者集合标签collection添加select属性来关联(通过sql的标志 id)指定查询语句 这样可以简化sql语句的编写
<resultMap id="blogResult" type="Blog">
<association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap>
<select id="selectBlog" resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
</select>
<select id="selectAuthor" resultType="Author">
SELECT * FROM AUTHOR WHERE ID = #{id}
</select>
缓存
mybatis分为一级和二级缓存
一级缓存是基于一次会话 及同一个SqlSession 会话的(sqlSessionFactory.openSession())
是自动打开的 ;
二级缓存 做到从不同的缓存中共享数据
SqlSessionFactory 的缓存 缓存只作用于 cache 标签所在的映射文件中的语句
是需要在mapper文件里添加
<cache
eviction="FIFO" 清除策略
flushInterval="60000" 刷新时间
size="512" 缓存数量
readOnly="true"/> 只读
清除策略有:
LRU
– 最近最少使用:移除最长时间不被使用的对象。FIFO
– 先进先出:按对象进入缓存的顺序来移除它们。SOFT
– 软引用:基于垃圾回收器状态和软引用规则移除对象。WEAK
– 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。
好了不做太多总结了 基本上在官网上都可以查的到 需要用到的时候在找 官网有中文版的哦