MyBatis简单使用
MyBatis
认识MyBatis
MyBayis介绍
mybatis是Apache软件基金会下的一个开源项目,前身是Ibatis框架。2010年这个项目由apache 软件基金会迁移到google code下,改名为mybatis。2013年11月又迁移到了github(https://github.com/mybatis/mybatis-3/releases)
mybatis是一个开源的数据持久层框架,它内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所以的JDBC代码和参数和手工设置以及结果集的检索。开发者只需要关注业务本身,不需要花费精力去处理加载驱动、创建数据库连接对象、创建statement语句对象、参数设置、结果集处理等一系列繁杂的过程代码。
什么是ORM
ORM 全称 Object/Relational Mapper 即对象/关系映射,是一种数据持久化技术
在对象模型和关系型数据库之间建立对应关系,提供一种机制,通过JavaBead对象去操作数据库表中的数据
Mybatis 环境搭建
导入jar
-
通过设置maven项目里的pop.xml文件
在dependencies标签中添加所需的jar依赖
<!--junit jar--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <!--mysql jar--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.17</version> </dependency> <!-- mybatis jar --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <!--log4j jar--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
-
要使用 MyBatis, 只需将 所需的jar 文件置于 classpath 中即可。
创建和配置mybatis核心配置文件mybatis-config.xml
-
创建mybatis核心配置文件mybatis-config.xml
MyBatis核心配置文件主要用于配置数据库连接和MyBatis运行时所需的各种特性,包括了设置和影响 MyBatis行为的属性。
为了方便管理以后个各框架集成所需的配置文件,故需在项目工程下新建Source Folder 类型的resources目录,mybatis核心配置文件就是放在这个目录下
核心配置文件的名字默认是“configuration.xml”。但是为了方便在框架集成时更好地区分各个配置文件,mybatis一般命名为“mybatis-config.xml”。
-
配置
<?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="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="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
-
常用元素:
-
configuration
:整个 XML 配置文件的根节点,其角色就相当于是 MyBatis 的总管, MyBatis 所有 的配置信息都会存放在它里面 -
properties
:可通过外部指定的方式,将数据库连接相关信息配置在典型的 Java 属性配置文件中 (如database. properties),并使用这些属性对配置项实现动态配置。即通过 resource 属性从外部指定 properties 属性文件( database.properties ),代码如下<!--database.properties: 部分内容:--> driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/smbms?userUnicode=true&characterEncoding=utf-8&&zeroDateTimeBehavior=convertToNull username=root password=root
<!--mybatis-config.xml 部分内容:--> <configuration> <!-- 引入 database.properties 文件 --> <properties resource="database.properties" /> ...... <!-- 在配置数据源的地方直接用${key}引用 --> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </configuration>
也可以直接配置为 xml ,并使用这些属性对配置项实现动态配置
代码如下:
<!--mybatis-config.xml 部分内容:--> <!--properties 元素中直接配置 property 属性--> <properties> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms?userUnicode=true&characterEncoding=utf-8&&zeroDateTimeBehavior=convertToNull"/> <property name="username" value="root"/> <property name="password" value="root"/> </properties> <!-- 在配置数据源的地方直接用${key}引用 --> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource>
优先级: resource 属性值的优先级高于 property子节点配置的值。
-
typeAliases
typeAliases 元素的作用是配置类型别名,通过与 MyBatis 的 SQL 映射文件相关联,减少输入多余的完整类名,以简化操作。具体配置如下:
<typeAliases> <!--这里给实体类取别名,方便在 mapper 配置文件中使用--> <typeAlias alias="User" type="pojo.User"/> </typeAliases>
以上这种写法的弊端在于如果一个项目中有多个 POJO 的时候,需要一一进行配置,所以有更加简化的写法,就是通过 package 的 name 属性直接指定包名, MyBatis 会自动扫描指定包下的 JavaBean ,并默认设置一个别名,默认名称为 JavaBean 的非限定类名。具体配置如下:
<typeAliases> <!--默认名称:指定包下 JavaBean 的非限定类名--> <package name ="cn.smbms.pojo" /> </typeAliases>
-
settings
: settings 元素的作用是设置一些非常重要的设置选项,用于设置和改变 MyBatis 运行中的 行为,比如此处设置 MyBatis 的 log 日志实现为 LOG4J,即使用 log4j 实现日志功能。
常用配置如下表:
设置项 描述 允许值 默认值 cacheEnabled 对在此配置文件下的所有 cache 进行全局性开/关设置 true/false true lazyLoadingEnabled 全局性设置懒加载。如果设为 false ,则所有相关联的都会被初始化加载 true/false true autoMappingBehavior MyBatis对于resultMap自动映射匹配级别 NONE /PARTIAL: /FULL PARTIAL logImpl 指定 Mybatis 所用日志的具体实现,未指定时将自动查找 SLF4J | LOG4J | LOG4J2 |… Not MappingBehavior 讲解:
Mybatis的自动映射策略默认是开启的,而且默认是只对非嵌套的resultMap进行自动映射。这是通过Mybatis的全局配置autoMappingBehavior参数配置的。它一共有三种取值,分别是NONE、PARTIAL和FULL。
NONE:表示不启用自动映射 PARTIAL:表示只对非嵌套的resultMap进行自动映射 FULL:表示对所有的resultMap都进行自动映射
-
environments
: 表示配置 MyBatis 的多套运行环境,MyBatis 可以配置多套运行环境,如开发环境、测试环境、生产环境等,我们可以灵活选择不同的配置,从而将 SQL 映射应用到不同的数据库环境上。这些不同的运行环境,就可以通过 environments 元素来配置。environments 元素节点下通过配置多个 environment 子元素节点,实现配置多套运行环境,但是不管增加几套运行环境,都必须要明确选择出当前的唯一一个运行环境(即默认运行环境:通过 default 指定)。
-
environment
:配置 MyBatis 的一套运行环境,需指定运行环境 ID、事务管理、数据源配置等相关信息 -
mappers
:用来定义 SQL 的映射语句,我们只需要告诉 MyBatis 去哪里找到这些 SQL 语句(即去哪里找相应的 SQL 映射文件),整个项目中可以有1个或多个SQL 映射文件。可以使用类资源路径或者 URL 等 映射方式有多种 方式一:使用类资源路径获取资源(推荐使用)
<!-- 将 mapper 映射文件加入到系统核心配置文件中 --> <mappers> <mapper resource="mapper/user/UserMapper.xml"/> </mappers> mapper: mappers 的子元素节点,具体指定 SQL 映射文件的路径,其中 resource 属性的值表述了 SQL 映射文件的路径。 注意:在mybatis的核心xml文件中放的路径都是全限定路径
方式二:使用 URL 获取资源
<mappers> <mapper url="file:///E:/sqlmappers/UserMapper.xml"/> <mapper url="file:///E:/sqlmappers/ProviderMapper.xml"/> </mappers>
方式三:使用 package获取资源
<mappers> <package name="映射文件所在包名">4 </mappers>注意:这种方式必须保证接口名和 SQL 映射文件名相同,还必须在同一个包中。
方式四:
<mappers> <mapper class="mapper.user.ProviderMapper"/> </mappers> 注意: 1、这种方式必须保证接口名和 SQL 映射文件名相同,还必须在同一个包中。 2、使用此方式对于接口方法使用注解方式来说,没有同包同名的限制条件。
-
-
元素的顺序
mybatis-config.xml 文件的元素节点是有一定顺序的,节点位置若不按顺序排位,那么 XML 文件会报 错。
-
创建持久化类(pojo)
持久化类是指其实例状态需要被MyBatis持久化到数据库中的类
一般是放在pojo包下
创建sql映射文件
一般表的sql映射文件放在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="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
-
顶级元素
-
mapper
:映射文件的根元素节点,只有一个属性namespace,属性namespace与对应接口的完全限定名保存一致,用于区分不同的mapper,全局唯一,绑定接口// UserMapper.java public interface UserMapper { public List<User> getUserListByUserName(String userName); }
<!--UserMapper.xml--> <mapper namespace="mapper.user.UserMapper"> </mapper>
-
cache
– 给定命名空间的缓存配置。 -
cache-ref
– 其他命名空间缓存配置的引用。 -
resultMap
– 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。-
<!--reultMap的元素结构--> <resultMap type="" id=""> <constructor><!-- 实例化类时,用来注入结果到构造方法中--> <idArg /><!-- 标记结果作为id--> <arg /><!-- 注入到构造方法的一个普通结果--> </constructor> <id /><!--用来表示哪个列的主键--> <result /><!--注入到字段或javaBean属性的普通结果--> <association property="" /><!-- 用于一对一关联--> <collection property=""/> <!-- 用于一对多关联--> <discriminator javaType=""> <!-- 使用结果值来决定使用哪个结果映射 --> <case value=""></case><!-- 基于某些值的结果映射 --> </discriminator> </resultMap>
-
-
sql
– 可被其他语句引用的可重用语句块。<!--创建sql语句块--> <sql id="customerColumns">username,jobs,phone </sql>
<!--查询--> <select id="findCustomerById" parameterType="Integer" resultType="com.wang.po.Customer"> select id, <!--引用--> <include refid="customerColumns"/> from t_customer where id=#{id} </select>
-
insert
– 映射插入语句 -
update
– 映射更新语句 -
delete
– 映射删除语句 -
select
– 映射查询语句
-
-
查询
-
Select 参数
属性 描述 id 在命名空间中唯一的标识符,可以被用来引用这条语句。 parameterType 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。 resultType 从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。 resultMap 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。 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 中的一个,默认值为 unset (依赖驱动)。 databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。 resultOrdered 这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。 resultSets 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。 -
注意:MyBatis传入参数类型可以是java基础数据类型,但是只适用于一个参数的情况,通过#{变量名}获取值。若是多参数入参,需要复杂数据类型来支持,包括java实体类、map,通过#{属性名}或#{键}来获取值
-
普通查询
// UserMapper.java public interface UserMapper { public List<User> getUserListByUserName(); }
<!--UserMapper.xml--> <!-- resultType 返回类型--> <select id="getUserListByUserName" resultType="User"> select * from smbms_user </select>
自动映射到User实体类中
-
单个参数
// UserMapper.java public interface UserMapper { public List<User> getUserListByUserName(String userName); }
<!--UserMapper.xml--> <!--根据用户名称查询用户列表(模糊查询) concat 连接字符串 resultType 返回类型, paramenterType传参类型--> <select id="getUserListByUserName" resultType="User" parameterType="String"> select * from smbms_user where userName like CONCAT ('%',#{userName},'%') </select>
通过设置parameterType参数来设置传递的参数类型 如果是单个参数 设置基础数据类型 通过
-
传入参数:对象
// UserMapper.java public interface UserMapper { public List<User> getUserListByUser(User user); }
<!--UserMapper.xml--> <!-- 查询用户列表(参数:对象入参) --> <select id="getUserListByUser" resultType="User" parameterType="User"> select * from smbms_user where userName like CONCAT ('%',#{userName},'%') and userRole = #{userRole} </select>
设置parameterType参数的值为实体类user对象 ,获取参数时使用#{字段名}来获取参数
-
传入参数:Map
// UserMapper.java public interface UserMapper { public List<User> getUserListByMap(Map<String, String> userMap); }
<!--UserMapper.xml--> <!-- 查询用户列表(参数:Map) --> <select id="getUserListByMap" resultType="User" parameterType="Map"> select * from smbms_user where userName like CONCAT ('%',#{uName},'%') and userRole = #{uRole} </select>
设置parameterType参数的值为Map对象 ,获取参数时使用#{键}来获取参数
-
多表查询
一个实体类里有其他实体类作为属性,这是我们无法通过一个实体类输出所有的字段,必须进行手动 映射,使用ResultMap。ResultMap进行手动映射也解决了字段信息与对象属性不一致的情况,在复杂联合查询中自由控制映射结果。
// UserMapper.xml <!-- 当数据库中的字段信息与对象的属性不一致时需要通过resultMap来映射,即将不同表合并成一张 --> <resultMap type="User" id="userList"> <result property="id" column="id" /> <result property="userCode" column="userCode" /> <result property="userName" column="userName" /> <result property="phone" column="phone" /> <result property="birthday" column="birthday" /> <result property="gender" column="gender" /> <result property="userRole" column="userRole" /> <result property="userRoleName" column="roleName" /> </resultMap> <select id="getUserListByUser" resultMap="userList" parameterType="User"> select u.*,r.roleName from smbms_user u,smbms_role r where u.userName like CONCAT ('%',#{userName},'%') and u.userRole = #{userRole} and u.userRole = r.id </select>
-
-
assocation
// UserMapper.xml <!-- 根据用户id获取用户列表 association start --> <resultMap type="User" id="userRoleList"> <id property="id" column="id" /> <result property="userCode" column="userCode" /> <result property="userName" column="userName" /> <result property="userRole" column="userRole" /> <!-- javaType=Role 对应JavaBean名 | column 对应数据库查询结果集的字段 | property 对应JavaBean的属性--> <association property="role" javaType="Role"> <id property="id" column="r_id" /> <result property="roleCode" column="roleCode" /> <result property="roleName" column="roleName" /> </association> </resultMap>
<select id="getUserListByRoleId" parameterType="Integer" resultMap="userRoleList"> select u.*,r.id as r_id,r.roleCode, r.roleName from smbms_user u,smbms_role r where u.userRole=#{userRole} and u.userRole = r.id </select> <!-- 根据用户id获取用户列表 association end -->
除了在resultMap直接使用 也可将resultMap用assocation导入使用达成同样的效果
// UserMapper.xml <!-- 根据用户id获取用户列表2 association start --> <resultMap type="User" id="userRoleList2"> <id property="id" column="id" /> <result property="userCode" column="userCode" /> <result property="userName" column="userName" /> <result property="userRole" column="userRole" /> <association property="role" javaType="Role" resultMap="roleResult" /> </resultMap> <resultMap type="Role" id="roleResult"> <id property="id" column="r_id" /> <result property="roleCode" column="roleCode" /> <result property="roleName" column="roleName" /> </resultMap> <select id="getUserListByRoleId" parameterType="Integer" resultMap="userRoleList"> select u.*,r.id as r_id,r.roleCode, r.roleName from smbms_user u,smbms_role r where u.userRole=#{userRole} and u.userRole = r.id </select> <!-- 根据用户id获取用户列表 association end -->
-
collection:
多表复杂数据联合查询如果有集合类型的数据,我们就需要用到collection了
// UserMapper.xml <!-- 获取指定用户的地址列表(user表-address表: 1对多) collection start --> <resultMap type="User" id="userAddressList"> <id property="id" column="id" /> <result property="userCode" column="userCode" /> <result property="userName" column="userName" /> <!-- ofType 对应JavaBean --> <collection property="addressList" ofType="Address"> <id property="id" column="a_id" /> <result property="postCode" column="postCode" /> <result property="tel" column="tel" /> <result property="contact" column="contact" /> <result property="addressDesc" column="addressDesc" /> </collection> </resultMap> <select id="getAddressListByUserId" parameterType="Integer" resultMap="userAddressList"> select u.*, a.id as a_id, a.contact, a.addressDesc, a.tel, a.postCode from smbms_user u, smbms_address a where u.id=a.userId and u.id=#{id} </select> <!-- 获取指定用户的地址列表(user表-address表: 1对多) collection end -->
还有一种方法实现跟assocation一样
// UserMapper.xml <!-- 获取指定用户的地址列表2(user表-address表: 1对多) collection start --> <resultMap type="User" id="userAddressList2"> <id property="id" column="id" /> <result property="userCode" column="userCode" /> <result property="userName" column="userName" /> <!-- ofType 对应JavaBean --> <collection property="addressList" ofType="Address"resultMap="addressResult"/> </resultMap> <resultMap type="Address" id="addressResult"> <id property="id" column="a_id" /> <result property="postCode" column="postCode" /> <result property="tel" column="tel" /> <result property="contact" column="contact" /> <result property="addressDesc" column="addressDesc" /> </resultMap> <select id="getAddressListByUserId2" parameterType="Integer" resultMap="userAddressList2"> select u.*, a.id as a_id, a.contact, a.addressDesc, a.tel, a.postCode from smbms_user u, smbms_address a where u.id=a.userId and u.id=#{id} </select> <!-- 获取指定用户的地址列表2(user表-address表: 1对多) collection end -->
-
-
增删改
-
Insert, Update 和 Delete 的属性
属性 说明 id 命名空间中的唯一标识符,可被用来代表这条语句。 parameterType 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。 flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值: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 的语句;如果带或者不带的语句都有,则不带的会被忽略。 -
insert
// UserMapper.xml <!-- 增加新用户 --> <insert id="addUser" parameterType="User"> insert into smbms_user (userCode,userName,userPassword,gender,birthday,phone, address,userRole,createdBy,creationDate) values (#{userCode}, #{userName}, #{userPassword},#{gender},#{birthday}, #{phone},#{address},#{userRole},#{createdBy},#{creationDate}) </insert>
-
update
// UserMapper.xml <!-- 修改用户信息 --> <update id="modify" parameterType="User"> update smbms_user set userCode=#{userCode},userName=#{userName},userPassword=#{userPassword}, gender=#{gender},birthday=#{birthday},phone=#{phone},address=#{address}, userRole=#{userRole},modifyBy=#{modifyBy},modifyDate=#{modifyDate} where id = #{id} </update>
-
delete
```xml
// UserMapper.xml
<!-- 根据用户id删除用户信息 -->
<delete id="deleteUserById">
delete from smbms_user where id = #{id}
</delete>
```
使用
基本使用
步骤
-
读取配置文件;
-
通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
-
通过SqlSessionFactory创建SqlSession。
-
调用SqlSession的操作数据库方法。
-
关闭SqlSession。
-
代码示例
//log4j对象 Logger logger = Logger.getLogger(test.class); String resource = "mybatis-config.xml"; //mybtis配置文件路径 @Test public void test1(){ //获取输入流 InputStream is = null; try { is = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } //创建sqlSessionFactory对象 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); //创建SqlSession对象 SqlSession sqlSession = factory.openSession(); //Mybatis通过mapper文件的namespace和子元素的id来找到对应的SQL,从而执行查询操作 int count = sqlSession.selectOne("count"); //使用logger输出 logger.debug("UserMapperTest count--->" + count); //关闭sqlSession对象 sqlSession.close(); }
创建工具类使用
步骤
-
创建工具类MyBatisUtils
package 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.IOException; import java.io.InputStream; /** * myBatis工具类 * 作者:weisen * 日期:2019/9/16 10:58 */ public class MyBatisUtils { private static SqlSessionFactory factory; static { try { InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(is); } catch (IOException e) { e.printStackTrace(); } } /** * 获取执行对象 * @return sqlSession对象 */ public static SqlSession createSqlSession(){ return factory.openSession(false); //true为自动提交事务 } /** * 关闭 * @param sqlSession 执行对象 */ public static void closeSqlSession(SqlSession sqlSession){ if (null != sqlSession){ sqlSession.close(); } } }
-
通过工具类获取SqlSession对象
-
调用SqlSession的操作数据库方法。
-
通过工具类关闭SqlSession对象
SqlSession sqlSession = null; List<User> userList = new ArrayList<>(); try{ //获取 sqlSession = MyBatisUtils.createSqlSession(); //通过映射接口调用方法 userList = sqlSession.getMapper(UserMapper.class).getUserList(); } catch (Exception e) { e.printStackTrace(); }finally { //关闭 MyBatisUtils.closeSqlSession(sqlSession); } //输出 for (User user : userList) { logger.debug("testGetUserList userCode: " + user.getUserCode() + ",testGetUserList userName: " + user.getUserName() ); }
动态sql
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。
if
动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
where
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="title != null">
AND title like #{title}
</if>
</select>
上一个代码拼接后的sql 将会多出一个 and 这时候,就需要 where 来解决这个问题
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。这样 拼接后的代码就不会有问题了
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
choose, when, otherwise
有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
<!--当title和author都不为null的时候, 那么选择二选一(前者优先), 如果都为null, 那么就选择 otherwise中的, 如果tilte和author只有一个不为null, 那么就选择不为null的那个。-->
set
set 元素可以用于动态包含需要更新的列,set元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“set”子句。而且,若语句的结尾为“,”,set元素也会将它们去除。这样 拼接后的代码就不会有问题了
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
trim
trim标记是一个格式化的标记,可以完成set或者是where标记的功能,如下代码:
属性:
prefix:前缀
prefixoverride:去掉第一个指定的值
suffix:后缀
suffixoverride:去掉最后一个指定的值
foreach
动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:
<!--foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。-->
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<!--item:每次遍历时的对象 open:开头的值 close:结尾的值 separator:拼接符号 collection:遍历的类型,或者是map的key,数组是array 集合是list-->
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>