-
mybatis
mapper映射模式
-
目录结构
-
mybatis配置文件MybatisConfig.xml
<!-- development1使用的环境id--> <environments default="development1"> <!-- 配置环境id 可多个--> <environment id="development1"> <!-- 事务管理--> <transactionManager type="JDBC"> </transactionManager> <!-- 数据源 POOLED(池)--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 映射文件路径--> <mappers> <mapper resource="mapper/user.xml"></mapper> <mapper resource="mapper/role.xml"></mapper> </mappers> </configuration>
-
映射文件user.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"> <mapper namespace="user"> <resultMap id="resultUser" type="domain.entity.User"> <id column="id" property="id"></id> <result column="user_name" property="userName"></result> <result column="name" property="name"></result> <result column="brithday" property="brithday"></result> <result column="age" property="age"></result> </resultMap> <insert id="addUser" parameterType="domain.entity.User"> insert into user(user_name,name,brithday,age) values (#{userName},#{name},#{brithday},#{age}) </insert> <update id="updateUser" parameterType="domain.entity.User"> update user set user_name=#{userName},age=#{age} where id=#{id} </update> <select id="selectUserAll" resultMap="resultUser"> select * from user </select> <select id="selectUser" parameterType="long" resultMap="resultUser"> select * from user where id=#{id} </select> <delete id="deleteUser" parameterType="long"> delete from user where id=#{id} </delete> </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="role"> //在开发中,可直接映射到XXXmapper接口 <resultMap id="resultRole" type="domain.entity.Role"> <id column="id" property="id"></id> <result column="role_name" property="roleName"></result> <result column="role_code" property="roleCode"></result> </resultMap> <select id="selectUserAll" resultMap="resultRole"> select * from role </select> </mapper>
namespace="domain.entity.User"为别名,假如两个映射文件里有同名,则就不知道找哪个了,两个select标签名一致,如果不使用别名会报错
-
#、$
-
#{},#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
-
, {} , ,将传入的数据直接显示生成在sql中
-
#方式能够很大程度防止sql注入,$方式无法防止Sql注入。
-
$方式一般用于传入数据库对象,例如传入表名。
-
从安全性上考虑,能使用#尽量使用#来传参,因为这样可以有效防止SQL注入的问题。
-
-
-
测试代码
package domain.entity; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.jupiter.api.Test; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.List; public class UserTest { User user=new User(); @Test public void uTest(){ user.setAge(26); System.out.println(user.toString()); } public static SqlSessionFactory getSqlss(){ String resource="MybatisConfig.xml"; SqlSessionFactory sqlSessionFactory=null; try { InputStream inputStream=Resources.getResourceAsStream(resource); sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream); return sqlSessionFactory; } catch (IOException e) { e.printStackTrace(); } return sqlSessionFactory; } @Test public void addUserTest(){ user.setUserName("王1"); user.setName("1号"); user.setBrithday(new Date()); user.setAge(19); SqlSession sqlSession=UserTest.getSqlss().openSession(); sqlSession.insert("addUser",user); sqlSession.commit(); //System.out.println(UserTest.getSqlss()); } @Test public void updateUserTest(){ user.setId(2L); user.setUserName("王2"); user.setName("2号"); user.setBrithday(new Date()); user.setAge(29); SqlSession sqlSession=UserTest.getSqlss().openSession(); sqlSession.insert("updateUser",user); sqlSession.commit(); //System.out.println(UserTest.getSqlss()); } @Test public void selectUserAllTest(){ SqlSession sqlSession=UserTest.getSqlss().openSession(); List<User> userList=sqlSession.selectList("domain.entity.User.selectUserAll"); System.out.println(userList.toString()); } @Test public void selectUserTest(){ Long id=3L; SqlSession sqlSession=UserTest.getSqlss().openSession(); User user1=sqlSession.selectOne("selectUser",id); System.out.println(user1.toString()); } @Test public void deleteUserTest(){ Long id=3L; SqlSession sqlSession=UserTest.getSqlss().openSession(); sqlSession.delete("deleteUser",id); sqlSession.commit(); //增删改必须提交 //System.out.println(UserTest.getSqlss()); } //别名一致测试 @Test public void selectRoleAllTest(){ SqlSession sqlSession=UserTest.getSqlss().openSession(); List<User> userList=sqlSession.selectList("domain.entity.Role.selectUserAll"); System.out.println(userList.toString()); } }
mapper代理模式
-
其他配置不变,改变的是不需要使用名字取获取对于的xml映射文件
-
mapper接口
package infra.mapper; import domain.entity.Role; import java.util.List; public interface RoleMapper { public List<Role> selectRoleAll(); }
-
对应的映射文件
<?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="infra.mapper.RoleMapper"> <resultMap id="resultRole" type="domain.entity.Role"> <id column="id" property="id"></id> <result column="role_name" property="roleName"></result> <result column="role_code" property="roleCode"></result> </resultMap> <select id="selectRoleAll" resultMap="resultRole"> select * from role </select> </mapper>
namespace=“infra.mapper.RoleMapper”:这里不再是别名,而是对应mapper接口路径,完成接口与xml映射文件的绑定。在select标签中,id="selectRoleAll"为接口里面的方法名,这样一来就可以把方法和查询服务绑定在一起了
-
测试
public static SqlSessionFactory getSqlss(){ String resource="MybatisConfig.xml"; SqlSessionFactory sqlSessionFactory=null; try { InputStream inputStream=Resources.getResourceAsStream(resource); sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream); return sqlSessionFactory; } catch (IOException e) { e.printStackTrace(); } return sqlSessionFactory; } RoleMapper mapper=UserTest.getSqlss().openSession().getMapper(RoleMapper.class); //openSession()获取sqlSession @Test public void selectRoleAllTest1(){ List<Role> userList=mapper.selectRoleAll(); System.out.println(userList.toString()); }
-
打包
mvn clean install -Dmaven.test.skip=true -U
清理项目生产的临时文件,一般是模块下的target目录。同时执行模块安装命令 将打包的的jar/war文件复制到你的本地仓库中,供其他模块使用 -Dmaven.test.skip=true 跳过测试(同时会跳过test compile),而-U强制更新
-
动态sql
-
<select id="selectUserIf" resultMap="resultUser"> select * from user where <if test="ifId!=2L"> id=3 </if> </select>
public User selectUserIf(@Param("ifId") Long ifId);
@Test public void selectUserIfTest(){ User user2=userMapper.selectUserIf(1L); System.out.println(user2.toString()); //User{id=3, userName='王3', name='1号', brithday=Tue Jul 13 13:09:43 CST 2021, age=18, roleList=null} }
-
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除.
<select id="selectUserIf" resultMap="resultUser"> select * from user <where> <if test="ifId!=2L"> or id=3 </if> <if test="ifId!=2L"> or id=4 </if> </where> </select>
@Test public void selectUserIfTest(){ List<User> user2=userMapper.selectUserIf(1L); System.out.println(user2.toString()); // [User{id=3, userName='王3', name='1号', brithday=Tue Jul 13 13:09:43 CST 2021, age=18, roleList=null}, // User{id=4, userName='王4', name='1号', brithday=Tue Jul 13 13:09:46 CST 2021, age=17, roleList=null}] }
select * from user where id=3 or id=4
-
条件控制标签、、组合使用
<select id="selectUserIf" resultMap="resultUser"> select * from user <where> <choose> <when test="ifId!=2L"> id=3 </when> <otherwise> id=5 </otherwise> </choose> </where> </select>
@Test public void selectUserIfTest(){ List<User> user2=userMapper.selectUserIf(2L); System.out.println(user2.toString()); // [User{id=5, userName='王5', name='1号', brithday=Tue Jul 13 13:09:51 CST 2021, age=16, roleList=null}] }
等同于if,等同于else ,也可以sql里的 then
-
set标签用于update语句中,会自动去掉**’ ,’** (逗号)
<update id="updateUser" parameterType="domain.entity.User"> update user <set> <if test="id!=2L"> ,user_name=#{userName} </if> <if test="id!=2L"> ,age=#{age} </if> </set> <where> id=#{id} </where> </update>
@Testpublic void updateUserTest11(){ user.setId(4L); user.setUserName("王4"); user.setName("4号"); user.setBrithday(new Date()); user.setAge(24); userMapper.updateUser(user); UserTest.getSqlss().openSession().commit();}
-
常用于IN 语句
collection:参数里面的集合名
open: 开头自动拼接符号
close:结束自动拼接符号
separator:分隔符
item:迭代的元素名,该参数为必选。
index:迭代的序列号,在list和数组中,index是元素的序号,在map中,index是元素的key。
<select id="countByUserList" resultType="_int" parameterType="list"> select count(*) from users <where> id in <foreach item="item" collection="list" separator="," open="(" close=")" index=""> #{item.id, jdbcType=NUMERIC} </foreach> </where> </select>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B93IvHb1-1630748441226)(C:\Users\Administrator\Desktop\培训记录\随笔\用图\mybatis_foreach.png)]
-
一对一
property:对应User类的哪个字段;javaType:这个字段的类型
<resultMap id="resultUser" type="domain.entity.User"> <id column="id" property="id"></id> <result column="user_name" property="userName"></result> <result column="name" property="name"></result> <result column="brithday" property="brithday"></result> <result column="age" property="age"></result> <association property="role" javaType="domain.entity.Role"> <result column="role_name" property="roleName"></result> <result column="role_code" property="roleCode"></result> </association> </resultMap>
private Long id; private String userName; private String name; private Date brithday; private Integer age; private Role role;
联查得到一个用户对应一个角色,一对一 <select id="selectUserOneToOne" resultMap="resultUser"> SELECT user.*, role.role_code, role.role_name FROM user LEFT JOIN user_role ON USER.id = user_role.user_id LEFT JOIN role ON role.id = user_role.role_id WHERE user.id = 4 </select>
User{id=4, userName='王4', name='1号', brithday=Tue Jul 13 13:09:46 CST 2021, age=17, role=Role{id=null, roleName='分公司总经理', roleCode='003'}}
-
延迟加载的方式
fetchType:加载模式,使用lazy,延迟加载
select:关联的select语句id
column:查询出来的字段名,同时也作为关联select语句的参数,可以看到在selectUserRoleById里面查出来的字段有id作为查询结果,然后将这个查询结果作为selectRole的参数条件。
-
-
一对多
ofType:为list里面的类型
foreignColumn:
<resultMap id="resultUser" type="domain.entity.User"> <id column="id" property="id"></id> <result column="user_name" property="userName"></result> <result column="name" property="name"></result> <result column="brithday" property="brithday"></result> <result column="age" property="age"></result> <collection property="roleList" ofType="domain.entity.Role" foreignColumn="id"> <result column="role_name" property="roleName"></result> <result column="role_code" property="roleCode"></result> </collection> </resultMap>
一个人员拥有多个角色 [User{id=3, userName='王3', name='1号', brithday=Tue Jul 13 13:09:43 CST 2021, age=18, roleList=[Role{id=null, roleName='总经理', roleCode='001'}, Role{id=null, roleName='副总经理', roleCode='002'}]}]
-
延迟加载
-
-
多对多
-
mybatis全局配置文件
-
数据库配置文件
数据库文件 properties文件
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC username=root password=root
在mybatis配置文件XML文件中使用
<properties resource="db.properties" ></properties> //引入配置文件<dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/></dataSource>
-
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><!-- 属性 引入配置文件可使用--> <properties> <property name="" value=""/> <property name="" value=""/> </properties><!-- 设置 --> <settings> <setting name="" value=""/> </settings><!--别名--> <typeAliases> <package name=""/> </typeAliases><!-- 类处理器--> <typeHandlers> <package name=""/> </typeHandlers><!-- 对象工厂--> <objectFactory type=""> <property name="" value=""/> </objectFactory><!-- 插件--> <plugins> <plugin interceptor=""></plugin> </plugins><!-- 环境 default使用的环境ID--> <environments default=""><!-- 可多个环境--> <environment id=""><!-- 事务管理器--> <transactionManager type=""></transactionManager> <dataSource type=""></dataSource> </environment> </environments><!-- 映射器--> <mappers> <package name=""/> <mapper resource=""></mapper> <mapper class=""></mapper> <mapper url="" ></mapper> </mappers></configuration>
-
properties 属性
<!--<properties resource="db.properties" ></properties> 不用url--> <properties resource="db.properties"> <!-- 修改db配置文件属性 --> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="root"/> </properties>
-
setting 设置
MyBatis 中极为重要的调整设置
<settings><!-- 将lazyLoadingEnabled设置为true表示开启延迟加载,默认为false--> <setting name="lazyLoadingEnabled" value="true"/><!--将aggressiveLazyLoading设置为false表示按需加载,默认为true--> <setting name="aggressiveLazyLoading" value="false"/> </settings>
设置名 描述 有效值 默认值 cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType
属性来覆盖该项的开关状态。true | false false aggressiveLazyLoading 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods
)。true | false false (在 3.4.1 及之前的版本中默认为 true) multipleResultSetsEnabled 是否允许单个语句返回多结果集(需要数据库驱动支持)。 true | false true useColumnLabel 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 true | false true useGeneratedKeys 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 true | false False autoMappingBehavior 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 NONE, PARTIAL, FULL PARTIAL autoMappingUnknownColumnBehavior 指定发现自动映射目标未知列(或未知属性类型)的行为。 NONE
: 不做任何反应WARNING
: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'
的日志等级必须设置为WARN
)FAILING
: 映射失败 (抛出SqlSessionException
)NONE, WARNING, FAILING NONE defaultExecutorType 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。 SIMPLE REUSE BATCH SIMPLE defaultStatementTimeout 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 任意正整数 未设置 (null) defaultFetchSize 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 任意正整数 未设置 (null) defaultResultSetType 指定语句默认的滚动策略。(新增于 3.5.2) FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置) 未设置 (null) safeRowBoundsEnabled 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 true | false False safeResultHandlerEnabled 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 true | false True mapUnderscoreToCamelCase 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 true | false False localCacheScope MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 SESSION | STATEMENT SESSION jdbcTypeForNull 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 OTHER lazyLoadTriggerMethods 指定对象的哪些方法触发一次延迟加载。 用逗号分隔的方法列表。 equals,clone,hashCode,toString defaultScriptingLanguage 指定动态 SQL 生成使用的默认脚本语言。 一个类型别名或全限定类名。 org.apache.ibatis.scripting.xmltags.XMLLanguageDriver defaultEnumTypeHandler 指定 Enum 使用的默认 TypeHandler
。(新增于 3.4.5)一个类型别名或全限定类名。 org.apache.ibatis.type.EnumTypeHandler callSettersOnNulls 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 true | false false returnInstanceForEmptyRow 当返回行的所有列都是空时,MyBatis默认返回 null
。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2)true | false false logPrefix 指定 MyBatis 增加到日志名称的前缀。 任何字符串 未设置 logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置 proxyFactory 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 以上) vfsImpl 指定 VFS 的实现 自定义 VFS 的实现的类全限定名,以逗号分隔。 未设置 useActualParamName 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters
选项。(新增于 3.4.1)true | false true configurationFactory 指定一个提供 Configuration
实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration()
的方法。(新增于 3.2.3)一个类型别名或完全限定类名。 未设置 shrinkWhitespacesInSql 从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5) true | false false defaultSqlProviderType Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type
(orvalue
) attribute on sql provider annotation(e.g.@SelectProvider
), when these attribute was omitted.A type alias or fully qualified class name Not set -
typeAliases 别名
<typeAliases> <typeAlias type="domain.entity.Role" alias="Role1"></typeAlias></typeAliases>
#原:<resultMap id="resultRole" type="domain.entity.Role"> <id column="id" property="id"></id> <result column="role_name" property="roleName"></result> <result column="role_code" property="roleCode"></result> </resultMap>#别名后:<resultMap id="resultRole" type="Role1"> <id column="id" property="id"></id> <result column="role_name" property="roleName"></result> <result column="role_code" property="roleCode"></result></resultMap><select id="selectRoleAll" resultMap="resultRole"> select * from role</select>
在Mybatis本身就已经内置了一部分基础类型的别名
别名 映射的类型 _byte byte _long long _short short _int int _integer int _double double _float float _boolean boolean string String byte Byte long Long short Short int Integer integer Integer double Double float Float boolean Boolean date Date decimal BigDecimal bigdecimal BigDecimal object Object map Map hashmap HashMap list List arraylist ArrayList collection Collection iterator Iterator -
typeHandlers 类处理器
MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
类型处理器 Java 类型 JDBC 类型 BooleanTypeHandler
java.lang.Boolean
,boolean
数据库兼容的 BOOLEAN
ByteTypeHandler
java.lang.Byte
,byte
数据库兼容的 NUMERIC
或BYTE
ShortTypeHandler
java.lang.Short
,short
数据库兼容的 NUMERIC
或SMALLINT
IntegerTypeHandler
java.lang.Integer
,int
数据库兼容的 NUMERIC
或INTEGER
LongTypeHandler
java.lang.Long
,long
数据库兼容的 NUMERIC
或BIGINT
FloatTypeHandler
java.lang.Float
,float
数据库兼容的 NUMERIC
或FLOAT
DoubleTypeHandler
java.lang.Double
,double
数据库兼容的 NUMERIC
或DOUBLE
BigDecimalTypeHandler
java.math.BigDecimal
数据库兼容的 NUMERIC
或DECIMAL
StringTypeHandler
java.lang.String
CHAR
,VARCHAR
ClobReaderTypeHandler
java.io.Reader
- ClobTypeHandler
java.lang.String
CLOB
,LONGVARCHAR
NStringTypeHandler
java.lang.String
NVARCHAR
,NCHAR
NClobTypeHandler
java.lang.String
NCLOB
BlobInputStreamTypeHandler
java.io.InputStream
- ByteArrayTypeHandler
byte[]
数据库兼容的字节流类型 BlobTypeHandler
byte[]
BLOB
,LONGVARBINARY
DateTypeHandler
java.util.Date
TIMESTAMP
DateOnlyTypeHandler
java.util.Date
DATE
TimeOnlyTypeHandler
java.util.Date
TIME
SqlTimestampTypeHandler
java.sql.Timestamp
TIMESTAMP
SqlDateTypeHandler
java.sql.Date
DATE
SqlTimeTypeHandler
java.sql.Time
TIME
ObjectTypeHandler
Any OTHER
或未指定类型EnumTypeHandler
Enumeration Type VARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值) EnumOrdinalTypeHandler
Enumeration Type 任何兼容的 NUMERIC
或DOUBLE
类型,用来存储枚举的序数值(而不是名称)。SqlxmlTypeHandler
java.lang.String
SQLXML
InstantTypeHandler
java.time.Instant
TIMESTAMP
LocalDateTimeTypeHandler
java.time.LocalDateTime
TIMESTAMP
LocalDateTypeHandler
java.time.LocalDate
DATE
LocalTimeTypeHandler
java.time.LocalTime
TIME
OffsetDateTimeTypeHandler
java.time.OffsetDateTime
TIMESTAMP
OffsetTimeTypeHandler
java.time.OffsetTime
TIME
ZonedDateTimeTypeHandler
java.time.ZonedDateTime
TIMESTAMP
YearTypeHandler
java.time.Year
INTEGER
MonthTypeHandler
java.time.Month
INTEGER
YearMonthTypeHandler
java.time.YearMonth
VARCHAR
或LONGVARCHAR
JapaneseDateTypeHandler
java.time.chrono.JapaneseDate
DATE
-
插件
-
环境
-
mapper 映射器
<!-- 使用相对于类路径的资源引用 --><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><!-- 将包内的映射器接口实现全部注册为映射器 -->org.mybatis.builder为包名<mappers> <package name="org.mybatis.builder"/></mappers>
-
-
映射文件
parameterType:传入参数类型
resultType:返回参数类型
resultMap:配置的resultMap标签ID
属性 描述 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
这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。 对于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动,MyBatis 有另外一种方法来生成主键。(不会)
<selectKey keyProperty="id" resultType="int" order="BEFORE" statementType="PREPARED">
属性 描述 keyProperty
selectKey
语句结果应该被设置到的目标属性。如果生成列不止一个,可以用逗号分隔多个属性名称。keyColumn
返回结果集中生成列属性的列名。如果生成列不止一个,可以用逗号分隔多个属性名称。 resultType
结果的类型。通常 MyBatis 可以推断出来,但是为了更加准确,写上也不会有什么问题。MyBatis 允许将任何简单类型用作主键的类型,包括字符串。如果生成列不止一个,则可以使用包含期望属性的 Object 或 Map。 order
可以设置为 BEFORE
或AFTER
。如果设置为BEFORE
,那么它首先会生成主键,设置keyProperty
再执行插入语句。如果设置为AFTER
,那么先执行插入语句,然后是selectKey
中的语句 - 这和 Oracle 数据库的行为相似,在插入语句内部可能有嵌入索引调用。statementType
和前面一样,MyBatis 支持 STATEMENT
,PREPARED
和CALLABLE
类型的映射语句,分别代表Statement
,PreparedStatement
和CallableStatement
类型。 -
mybatis缓存机制
-
一级缓存
一级缓存是SqlSession级别的缓存(默认是支持一级缓存,不需要再配置文件中配置一级缓存),在操作数据库时,每个SqlSession类的实例对象中有一个数据结构(HashMap)可以用来存储缓存数据,不同的SqlSession类的实例对象缓存的数据区域(HashMap)是互不影响的。当在同一个SqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据写到内存中,第二次查询不执行sql直接从内存中获取。
同一个sqlsession的同一个sql语句,第二次执行会直接从内存中获取。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wpzAf3ya-1630748606469)(C:\Users\Administrator\Desktop\培训记录\随笔\用图\mybatis一级缓存.png)]
-
二级缓存
二级缓存是Mapper级别的缓存,多个SqlSession类的实例对象操作同一个Mapper配置文件中的sql语句,多个SqlSession类的实例对象可以共用二级缓存,二级缓存是跨SqlSession的。
一个Mapper有一个自己的二级缓存区域(按照namespace划分),两个Mapper的namespace如果相同,那么这两个Mapper执行的sql查询会被缓存在同一个二级缓存中。
# 开启二级缓存<settings> <setting name="cacheEnabled" value="true"/></settings>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-topieWv0-1630748606470)(C:\Users\Administrator\Desktop\培训记录\随笔\用图\mybatis二级缓存.png)]
二级缓存会存在一个问题就是Mybatis框架不集成第三方缓存系统的话,就会面临分布式储存中脏数据的问题。A、B两台服务器的缓存可能会出现不一致的情况。
缓存存在自己的主机里,其他主机访问不到,所以数据不一致。
-
-