目录
7、将SqlSessionFactory设计成单例模式,做一个工具类
MyBatis简介
MyBatis的前身就是iBatis,iBatis本是由Clinton Begin开发,后来捐给Apache基金会,成立了iBatis开源项目。2010年5月该项目由Apahce基金会迁移到了Google Code,并且改名为MyBatis。
MyBatis是一个数据持久层(ORM)框架。把实体类和SQL语句之间建立了映射关系,是一种半自动化的ORM实现。
MyBatis的优点:
1.基于SQL语法,简单易学。
2.能了解底层组装过程。
3.SQL语句封装在配置文件中,便于统一管理与维护,降低了程序的耦合度。
4.程序调试方便。
与传统jdbc的比较
减少了60%的代码量
最简单的持久化框架
架构级性能增强
SQL代码从程序代码中彻底分离,可重用
增强了项目中的分工
强了移植性
Mybatis使用基本要素
一、mybatis-config .xml 全局配置文件
二、mapper.xml 核心映射文件
三、SqlSession接口
全局配置文件
mybatis-config.xml是系统的核心配置文件,包含数据源和事务管理器等设置和属性信息,XML文档结构如下:
configuration:全局环境配置 :用于配置mybatis全局属性
properties :可以以properties进行配置属性信息并在配置文件中使用可以省略
在当前文件中可以直接使用name当中数据进行使用,也可以读取properties文件,如下:
settings :修改 MyBatis 在运行时的行为方式(通常使用默认值或只修改制定数据值)
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="30"/>
<setting name="defaultFetchSize" value="200"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
设置参数 | 描述 | 有效值 | 默认值 |
cacheEnabled | 该配置影响的所有映射器中配置的缓存的全局开关 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态 | true | false | false |
aggressiveLazyLoading | 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 | true | false | 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 |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | Any positive integer | Not Set (null) |
defaultFetchSize | Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a query setting. | Any positive integer | Not Set (null) |
safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds)。 | true | false | False |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成的默认语言。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 | true | false | false |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | Any String | Not set |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
proxyFactory | 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 or above) |
typeAliases : 为 Java 类型命名一个短的名字(在之后进行数据操作时使用)
typeHandlers :类型处理器,MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。默认已经提供了默认的类型处理器,可以通过这个属性进行自定义类型处理器的使用,具体可以参考https://blog.csdn.net/qq_41879343/article/details/104915460
objectFactory :对象工厂, 每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现,具体可以参考https://blog.csdn.net/qq_41879343/article/details/104915460
plugins 插件 :plugins插件,MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 发行包中的源代码。 如果你想做的不仅仅是监控方法的调用,那么你最好相当了解要重写的方法的行为。 因为在试图修改或重写已有方法的行为时,很可能会破坏 MyBatis 的核心模块。 这些都是更底层的类和方法,所以使用插件的时候要特别当心。
environments :配置数据库相关环境
1)MyBatis可以配置多种环境,比如开发、测试和生产环境需要有不同的配置
2)每种环境使用一个environment标签进行配置并指定唯一标识符
3)可以通过environments标签中的default属性指定一个环境的标识符来快速的切换环境
4)environment-指定具体环境
environment :环境变量 ,书写在environments中 拥有id属性指定当前环境的唯一标识 可以用environments defaule属性指向
transactionManager :事务管理器,书写在environment中 拥有type属性,值可以书写:
1)JDBC - 这个类型直接全部使用 JDBC 的提交和回滚功能。它依靠使用连接的数据源来管理事务的作用域。
2)MANAGED - 这个类型什么不做 , 它从不提交 、 回滚和关闭连接 。 而是让窗口来管理事务的全部生命周期 。
3)自定义 - 实现TransactionFactory接口,type=全类名/别名
dataSource :数据源 ,书写在environment中 拥有type属性,值可以书写:
1)UNPOOLED:不使用连接池, UnpooledDataSourceFactory
2)POOLED:使用连接池, PooledDataSourceFactory
3)JNDI: 在EJB 或应用服务器这类容器中查找指定的数据源
4)自定义:实现DataSourceFactory接口,定义数据源的获取方式。
mappers :映射器
1)用来在mybatis初始化的时候,告诉mybatis需要引入哪些Mapper映射文件
2) mapper逐个注册SQL映射文件
mapper:映射 具体的映射方式
resource属性:单独引入相应xml配置(可以通过mapper配置中的namespace与id动态执行)
class属性:单独引入mapper接口对象(可以自动扫描与mapper接口名字相同的xml,class与xml同一目录)
package属性:引入指定包下接口对象(可以自动扫描与mapper接口名字相同的xml,class与xml同一目录)
Mapper配置文件
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
mapper:mapper配置文件根目录,拥有namespace属性
在MyBatis中,Mapper中的namespace用于绑定Dao接口的,即面向接口编程。 它的好处在于当使用了namespace之后就可以不用写接口实现类,业务逻辑会直接通过这个绑定寻找到相对应的SQL语句进行对应的数据处理
值拥有两种书写方法:
1) 短名称(比如“selectAllThings”)如果全局唯一也可以作为一个单独的引用
<mapper namespace="user"><mapper/>
2)接口完全限定名
<!--配置在核心配置文件中-->
<typeAliases>
<typeAlias alias="user" type="com.dao.UserDao"/>
</typeAliases>
<!--mapper配置文件引用别名 user代表接口名-->
<mapper namespace="user"><mapper/>
<!--也可以不使用别名直接填写接口名-->
<mapper namespace="com.dao.UserDao"><mapper/>
select:书写在mapper标签中的标签,拥有如下属性
属性 | 描述 |
---|---|
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 | 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。 |
Insert, Update, Delete:书写在mapper标签中的标签,拥有如下属性
属性 | 描述 |
---|---|
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 的语句;如果带或者不带的语句都有,则不带的会被忽略。 |
cache:二级缓存标签,书写在mapper标签中 无属性,需要在mybatis.xml中配置开启二级缓存(默认开启)
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
mybatis的二级缓存默认在缓存在内存中,不支持分布式服务器的缓存,所以,一般使用第三方的缓存插件,比如ehcache,redis
useCache:属性,对于开启二级缓存的查询,每次会先去缓存进行查找之后才会执行,如果不想让当前执行查询使用缓存需要将值设置为false
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
sql…
</select>
flushCache: 属性在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。 设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
sql…
</insert>
resultMap :用来描述获取数据后与对象的映射(数据库字段与对象属性名),通常情况下使用默认的映射(数据库字段与属性名相同),但有时需要进行不同的映射,这时候就需要使用requestMap进行设置在resultType中使用。具体如下:
id:标签,用来标识主键
column:数据库字段属性 property:实体类字段属性
result:标签 ,用于其他列标识
colleaction:标签,用来标识集合属性
property:实体类字段属性
ofType:集合存储数据类型属性
column属性:用于标识查询数据列(会获取对应列数据传入相应的查询语句)
select属性:懒加载执行时调用获取数据的方法(可以调用其他mapper中的方法,通过namespace.id使用)
fetchType:局部懒加载默认fetchType="lazy"深入式 eager侵入式
association:标签,用于标识类属性
property:实体类字段属性
javaType:类类型属性
column属性:用于标识查询数据列(会获取对应列数据传入相应的查询语句)
select属性:懒加载执行时调用获取数据的方法(可以调用其他mapper中的方法,通过namespace.id使用)
fetchType:局部懒加载默认fetchType="lazy"深入式 eager侵入式
sql:标签, 可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化. 比如:
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
include:标签, 可以调用定义的sql标签,可以设置property标签 设置name属性与value属性为sql标签中设置的参数赋值
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
动态sql标签
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
if 标签
使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。比如:
<select id="findUserWhereId" resultType="User">
SELECT * FROM User
WHERE state = 0
<if test="id != null">
AND id = #{id}
</if>
</select>
choose、when、otherwise 标签
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句
<select id="findUser" resultType="User">
SELECT * FROM User WHERE state = 0
<choose>
<when test="id != null">
AND title like #{id}
</when>
<when test="name!= null">
AND name like '%#{name}$'
</when>
<otherwise>
AND sal= 1
</otherwise>
</choose>
</select>
trim、where、set标签
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
<select id="findUser" resultType="User">
SELECT * FROM User
<where>
<if test="id != null">
state = #{state}
</if>
<if test="name!= null">
AND title like #{title}
</if>
</where>
</select>
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素
prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的).上述例子会移除所有prefixOverrides属性中指定的内容,并且插入 prefix 属性中指定的内容。
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:
<update id="updateUserIfNecessary">
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>
foreach遍历标签
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
item:遍历取出的数据
index:遍历数据的索引
colleaction:遍历的数据集合
open:开始拼接时添加的字符串
separator:每次遍历中间的字符串
close:结束后最后添加的字符串
javaWeb项目进行mybatis搭建
1、导入相应jar包
MyBatis是一个数据持久层(ORM)框架,所以进行使用时需要使用3个jar包
(1)mybaties的jar包 (2)log4j的jar包 (3)连接数据库的jar包
2、书写配置文件
使用简单配置完成搭建,所以只配置一些基本就可以了,在src下新建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">
<!-- 使用jdbc的事务,mybatis进行管理 -->
<transactionManager type="JDBC" />
<!-- 使用jdbc的连接池连接数据库 -->
<!-- 如果配置了<properties resource="db.properties"/> -->
<!-- value可以使用value="${driver}"的形式进行书写 /> -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydb" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 映射文件的配置-->
<mappers>
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>
3、创建相应数据库
create table t_user(
id int primary key auto_increment,
name varchar(20),
sal double,
birthday date
);
insert into t_user values(1,'鲁智深',200,now());
insert into t_user values(2,'武松',188,now());
select * from t_user;
4、创建映射实体类
数据类型必须映射一致,属性名可以与列名不一致,但需要书写requestMap进行映射否则会出现问题
package cn.com.bochy.entity;
import java.util.Date;
public class User {
private int id;
private String name;
private double sal;
private Date birthday;
get....
set.....
}
5、存放增删改查sql的配置文件
一般名字为: 类名Mapper.xml或类名Dao.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唯一表示此名字下的crud语句
-->
<mapper namespace="user">
<!--
id:在此命名空间下唯一标识
resultType:查询结果的返回类型或者集合的泛型
-->
<select id="selectAllUser" resultType="cn.com.bochy.entity.User">
select * from t_user
</select>
<!--
<insert id=""></insert>
<delete id=""></delete>
<update id=""></update>
-->
</mapper>
6、加入log4j日志
查看程序运行的状态。在根目录下新建一个log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
7、将SqlSessionFactory设计成单例模式,做一个工具类
就是将读取配置文件的过程封装成单例,避免使用时重复读取配置文件
package cn.com.bochy.util;
import java.io.IOException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisUtil {
private MyBatisUtil(){}
private static SqlSessionFactory sqlSessionFactory;
static{
try {
sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
8、代码测试
public class MyBatisTest {
@Test
public void test_selectAllUser() throws Exception{
//1、创建SqlSessionFactory对象,也是单例模式的
SqlSessionFactory factory = MyBatisUitl.getSqlSessionFactory();
//2、创建SqlSession对象
SqlSession session = factory.openSession();
//3、调用session的方法namespace的名字.id
List<User> users = session.selectList("user.selectAllUser");
//4、打印测试
for(User u:users){
System.out.println(u);
}
//5、关闭资源
session.close();
}
}
mybatis注解开发
mybatis可以使用xml文件来写sql语句,也可以通过注解来编写简单的sql语句,参考官方文档
在之前的开发中,我们使用mybatis,需要
1,配置文件,
2,然后创建dao接口,定义方法
3,再然后就要创建mapper.xml文件,在mapper.xml文件中编写sql语句,
4,最后再把mapper文件配置在mybatis主配置文件中就可以进行测试了
使用注解的方式,我们可以在dao接口中直接在方法上写sql语句,不需要创建mapper.xml文件了
使用注解也需要在mybatis配置文件中配置mapper接口的package扫描
常用注解
@Param()注解
语法:@Param(value="绑定值")可以简写为@Param("绑定值")
用于接口方法存在多个参数进行绑定传值
public int selectByNameAndJob(@Param("name")int name,@Param("job")int job);
@Select()注解
语法:@Select(value="查询语句")可以简写为@Select("查询语句")
等价于mapper.xml中的<select>
@Select("select * from emp")
List<Emp> allEmp();
@Insert()注解
语法:@Insert(value="添加语句")可以简写为@Insert("添加语句")
等价于mapper.xml中的<insert>
@Insert("insert into emp (ename,job,deptno,sal,hiredate) value(#{ename},#{job},#{deptno},#{sal},#{hiredate})")
int insertEmp(Emp emp);
@Update()注解
语法:@Update(value="修改语句")可以简写为@Update("修改语句")
等价于mapper.xml中的<update>
@Update("update emp set ename=#{ename} where empno=#{empno}")
int updateEmp(Emp emp);
@Delete()注解
语法:@Delete(value="删除语句")可以简写为@Select("删除语句")
等价于mapper.xml中的<delete>
@Delete("delete from emp where empno=#{empno}")
int deleteEmp(int empno);
@Results()注解
语法:@Results(id="唯一标识",value={result标签数组})
等价于mapper.xml中的<resultMap>
@Result()注解
语法:@Result(id="true/false是否为主键",column="数据库列",property="属性名")
等价于mapper.xml中的<result>与<id>
@Results(id="empMap",value={
@Result(id=true,column="eid",property="eid"),
@Result( column="ename",property="ename"),
@Result( column="ejob",property="ejob")
})
@resultMap()注解
语法:@resultMap(value="返回结果集映射id")可以简写为@resultMap("返回结果集映射id")
等价于mapper.xml中的resultMap属性
@Select("select * from emp")
@ResultMap("empMap")
List<Emp> allEmp();
使用注解完成动态sql的书写
使用Mybatis注解实现sql语句,但是有些时候有些字段是空的,这时候这个空的字段就要从条件查询语句中删除,这个时候就需要用到动态Sql。
使用方式很简单在原有的基础上使用{<script> sql语句 </script>}进行包裹即可
@Select({"<script> " +
"select * from t_user " +
"where 1=1 " +
"<if test='userId!=null'> and id = #{userId}</if> " +
"</script>"})
使用注解完成一对一sql的书写
@One()注解
语法:@One(select="执行方法",fetchType="加载方式(FetchType.LAZY深入懒加载)")
one是@Result标签的一个属性,添加后相当于将result标签转换为mapper.xml中的<association>
@Results(id = "empMap", value = {
@Result(id = true, column = "eid", property = "eid"),
@Result(column = "ename", property = "ename"),
@Result(column = "ejob", property = "ejob") ,
@Result(column = "dId", property = "dept",one=@One(select="selectById",fetchType=FetchType.LAZY))
})
@Select("select * from emp")
public ArrayList<Emp> selectEmp();
@Select("select * from dept where did=#{did}")
public Dept selectById(int did);
使用注解完成一对多sql的书写
@Many()注解
语法:@Many(select="执行方法",fetchType="加载方式(FetchType.LAZY深入懒加载)")
Many是@Result标签的一个属性,添加后相当于将result标签转换为mapper.xml中的<colleaction>
@Results(id = "empMap", value = {
@Result(id = true, column = "eid", property = "eid"),
@Result(column = "ename", property = "ename"),
@Result(column = "ejob", property = "ejob") ,
@Result(column = "dId", property = "dept",many=@Many(select="selectById",fetchType=FetchType.LAZY))
})
@Select("select * from emp")
public ArrayList<Emp> selectEmp();
@Select("select * from dept where did=#{did}")
public ArrayList<Dept> selectById(int did);
注意:在进行sql书写时常常将不同表sql书写在不同的位置,所以在进行一对一、一对多书写是select对应的值可以书写为接口全路径.方法名
mybatis逆向工程
1. 新建一个 Java Project 项目
新建一个 Java 项目,导入Mybatis逆向工程包mybatis-generator-core-1.3.2.jar
和数据库驱动包mysql-connector-java-5.1.39-bin.jar
。
2.逆向工程编写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="false" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/crm" userId="root"
password="root">
</jdbcConnection>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.yunhe.pojo"
targetProject="./src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.yunhe.mapper"
targetProject="./src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.yunhe.mapper"
targetProject="./src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table tableName="account"></table>
<table tableName="email"></table>
</context>
</generatorConfiguration>
3. 编写生成代码程序
最后编写一个简单的 Java 运行程序,运行后刷新工程就可以了。
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class TT {
public static void main(String[] args) throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//加载逆向生成配置文件信息
File configFile = new File("F://MyWork/RRR/src/a.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
逆向工程生成的Exmaple使用请见: