iBatis从3.x开始更名为MyBatis。除了Java以外,还有可用于.Net的Mybatis.Net。
相关依赖包(maven)
1
2
3
4
5
6
7
8
9
10<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.7</version> </dependency>
映射相关文件自动生成(mybatis-generator)
iBatis提供了Abator用于生成映射相关文件。Mybatis可以用mybatis generator实现类似功能。
生成配置文件
mybatis默认使用的路径和文件名(无需配置):src/main/resources/generatorConfig.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37<?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> <!-- classPathEntry:数据库的JDBC驱动--> <classPathEntry location="targetassistWEB-INFlibmysql-connector-java-5.1.32.jar"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <!-- 去除自动生成的注释 --> <commentGenerator> <property name="suppressAllComments" value="true"/> <property name="suppressDate" value="true"/> </commentGenerator> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/testdb?autoReconnect=true" userId="xxxx" password="xxxxx"/> <!-- 生成Model类,targetProject:自动生成代码的位置 --> <javaModelGenerator targetPackage="com.demo.models" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- 生成XML映射文件 --> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- 生成Mapper接口(DAO) --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.demo.mappers" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- 通过javaTypeResolver元素控制类型转化,也能继承JavaTypeResolver接口实现自己的类型转换器。 --> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> <!--将 JDBC DECIMAL和NUMERIC解析为Integer,而不是BigDecimal--> </javaTypeResolver> <!-- 要生成映射代码的数据表,tableName为表名;domainObjectName为对应的javaBean类名, enablexxxxx是与Example类相关的配置 --> <table tableName="person" domainObjectName="Person"/> <table tableName="my_table" domainObjectName="myTable" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> <!--<columnRenamingRule searchString="^D_" replaceString=""/>
<property name="useActualColumnNames" value="false"/>
--> </table> ...... </context> </generatorConfiguration>
- Example类实现了查询条件的对象化。
- "_"分隔的字段名会自动转化为驼峰形式。
- oracle nvarchar/nvarchar2类型会转化成Object类型。
- oracle指定精度的数值型字段默认转为BigDecimal,不指定精度的数值型默认转为Long。
- targetProject属性可以设置为MAVEN,代码将生成在target/generatored-source目录下。
- generatorConfiguration节点下添加 <properties resource="jdbc.properties" />,可以在配置中的${...}表示的占位符。获取文件的方式为:Thread.currentThread().getContextClassLoader().getResource(resource)
- context节点下添加<plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin> 生成的pojo类implements Serializable。
- 通过enableCountByExample, enableUpdateByExample, enableDeleteByExample, enableSelectByExample, selectByExampleQueryId等属性可以控制是否生成和使用xxxExample类在查询中替代模型类。
从属性文件中加载配置
generatorConfig.properties文件
1
2
3
4
5
6
7
8
9
10
11
12# 数据库驱动jar 路径 driver.class.path=target/assist/WEB-INF/lib/mysql-connector-java-5.1.32.jar
# 数据库连接参数 jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=utf-8 jdbc.username=uname
jdbc.password=pwd # 包路径配置 model.package=com.demo.modules.entity dao.package=com.demo.modules.mapper xml.mapper.package=com.demo.modules.mapper target.project=src/main/java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<?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> <properties url="${mybatis.generator.generatorConfig.properties}"> <!--maven pom文件properties中配置的属性--> <classPathEntry location="${driver.class.path}"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/> <!-- 生成Model类,targetProject:自动生成代码的位置 --> <javaModelGenerator targetPackage="${model.package}" targetProject="${target.project}"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> ...... </context> </generatorConfiguration>
构建时自动生成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <!-- 省缺值为:src/main/resources/generatorConfig.xml
<configurationFile>src/main/resources/mybatis-generator/generatorConfig.xml</configurationFile>--> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> <executions> <execution> <id>Generate MyBatis Artifacts</id> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin>
通过命令行调用
1
2mvn mybatis-generator:generate mvn mybatis-generator:generate -Dmybatis.generator.overwrite=true
直接执行
使用mybatis-generator-core-xxxx.jar包
1java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xml -overwrite
自定义类型转换
http://blog.csdn.net/lele2426/article/details/38794399
MyBatis映射相关文件
(1). model类 xxx.java
生成的model类是普通的java类,包含与数据库表各个字段对应的属性极其setter和getter方法。
(2). 查询条件类 xxxExample.java
http://openwares.net/database/mybatis_generator_example.html
Example类用于构造复杂的筛选条件。
Criterion
Criterion是最基本,最底层的Where条件,用于字段级的筛选。主要有以下这些:
- field IS NULL
- field IS NOT
- field > value
- field >= value
- field =value
- field <> value
- field <= value
- field < value
- field LIKE value
- field NOT LIKE value
- field BETWEEN value1 AND value2
- field IN (item1, item2,...)
- field NOT IN (item1, item2, ...)
LIKE模糊查询的%,?字符只能在构造查询条件是手动指定。
Mybatis Generator会为每个字段生成如上所示的Criterion,理论上可以构造任何筛选条件,如果字段较多生成的Example类会很大。
Criteria
Criteria包含了Cretiron的集合,同一个Criteria中的各个Cretiron之间为逻辑与(AND)关系。
oredCriteria
Example内有一个成员叫oredCriteria,是Criteria的集合,集合中的各个Criteria直接为逻辑或(OR)的关系。
用法
http://mybatis.org/generator/generatedobjects/exampleClassUsage.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20TestTableExample example = new TestTableExample(); example.or() .andField1EqualTo(5) .andField2IsNull(); example.or() .andField3NotEqualTo(9) .andField4IsNotNull(); List<Integer> field5Values = new ArrayList<Integer>(); field5Values.add(8); field5Values.add(11); field5Values.add(14); field5Values.add(22); example.or() .andField5In(field5Values); example.or() .andField6Between(3, 7);
- or()方法会产生一个新的Criteria对象,添加到oredCriteria中,并返回这个Criteria对象,从而可以链式表达,为其添加Criterion。
- Example类的distinct字段用于指定DISTINCT查询。
- orderByClause字段用于指定ORDER BY条件,这个条件没有构造方法,直接通过传递字符串值指定。
产生的SQL语句如下:
1
2
3
4where (field1 = 5 and field2 is null) or (field3 <> 9 and field4 is not null) or (field5 in (8, 11, 14, 22)) or (field6 between 3 and 7)
(3). xxxMapper.xml文件
sql语句映射配置文件。
- mapper元素需要有一个唯一的namespace属性,必须为对应的Mapper接口全名。
- 每个sql语句定义都有一个id,必须与对应的Mapper接口中方法同名,可以指定参数类型和返回类型。
- 每个sql语句可以定义parameterType和resultType指定参数和返回值类型,也可单独定义parameterMap(见后面的存储过程部分)和resultMap元素然后在sql语句元素中引用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130<?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.demo.mappers.PersonMapper"> <resultMap id="BaseResultMap" type="com.demo.models.Person"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> ...... </resultMap> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.demo.models.Person"> <result column="content" jdbcType="LONGVARCHAR" property="content" /> </resultMap>
<sql id="Update_By_Example_Where_Clause"> <where> <foreach collection="example.oredCriteria" item="criteria" separator="or"> <if test="criteria.valid"> <trim prefix="(" prefixOverrides="and" suffix=")"> <foreach collection="criteria.criteria" item="criterion"> <choose> <when test="criterion.noValue"> and ${criterion.condition} </when> <when test="criterion.singleValue"> and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue"> and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue"> and ${criterion.condition} <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Base_Column_List"> id, name </sql> <sql id="Blob_Column_List"> content </sql> <select id="selectByExampleWithBLOBs" parameterType="com.demos.models.PersonExample" resultMap="ResultMapWithBLOBs"> select <if test="distinct"> distinct </if> <include refid="Base_Column_List" /> , <include refid="Blob_Column_List" /> from person <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by $orderByClause$ </if> </select> <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="ResultMapWithBLOBs"> select <include refid="Base_Column_List" /> , <include refid="Blob_Column_List" /> from person where id = #{id,jdbcType=INTEGER} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> delete from person where id = #{id,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="com.demo.models.Person"> insert into person(id, name, content) values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR},#{content,jdbcType=LONGVARCHAR}) </insert> <insert id="insertSelective" parameterType="com.demo.models.Person"> insert into t_certstore <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null"> id, </if> <if test="name != null"> identityName, </if> <if test="content != null"> content, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null"> #{id,jdbcType=INTEGER}, </if> <if test="name!= null"> #{name,jdbcType=VARCHAR}, </if> <if test="content != null"> #{content,jdbcType=LONGVARCHAR}, </if> </trim> </insert> <update id="updateByExampleSelective" parameterType="map"> update person <set> <if test="record.id != null"> id = #{record.id,jdbcType=INTEGER}, </if> <if test="record.name!= null"> name = #{record.name,jdbcType=VARCHAR}, </if> <if test="record.content != null"> content = #{record.content,jdbcType=LONGVARCHAR}, </if> </set> <if test="_parameter != null"> <include refid="Update_By_Example_Where_Clause" /> </if> </update> <select id="countByExample" parameterType="com.demo.models.Person" resultType="java.lang.Integer"> select count(*) from person <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> </select> ...... </mapper>
xxxMapper.java(接口)
定义与Mapper.xml中sql语句对应的方法,方法名就是sql语句的id属性,参数和返回值也要对应。
1
2
3
4
5
6
7
8public interface PersonMapper { int countByExample(PersonExample example);int deleteByPrimaryKey(Integer id);
int insert(Personrecord); int insertSelective(Person record); List<CertStore> selectByExampleWithBLOBs(PersonExample example); CertStore selectByPrimaryKey(Integer id); int updateByExampleSelective(@Param("record") Person record, @Param("example") PersonExample example); ...... }
使用了多个参数的时候,可以用@Param注解给参数设置名字以区分不同参数,xml文件中sql语句的参数类型为map,通过参数名访问参数对象的属性。如@Param(record), 可用#{record.id}访问。还可以指定类型,如#{record.id,jdbcType=INTEGER}。
如果只有一个参数则不需要指定参数的名字,#{...}会直接访问这个参数对象的属性,如果没有适合的属性则直接代表当前参数。
- #{token} 会被预编译,能防止SQL注入
- ${token} 动态执行,不能防止SQL注入
Mybatis使用
mybatis配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<?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="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/testdb?autoReconnect=true" /> <property name="username" value="xxxx" /> <property name="password" value="xxxx" /> </dataSource> </environment> </environments> <settings>......</settings> <!-- 全局别名设置,在映射文件中只需写别名,而不必写出整个类路径 -->
<typeAliases>......</typeAliases>
<!-- 非注解的sql映射文件配置,如果使用mybatis注解,该mapper无需配置,但是如果mybatis注解中包含@resultMap注解,则mapper必须配置,给resultMap注解使用 --> <mappers> <mapper resource="mapper/Person.xml" /> <mapper class="com.demo.mapper.CustomPersonMapper" /> ...... </mappers> </configuration>
可以自行创建额外的sql映射xml文件或基于注解Mapper接口,但是都需要加入到Mybatis配置中的mappers元素里。
settings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<!-- 全局映射器启用缓存 --> <setting name="cacheEnabled" value="true" /> <!-- 查询时,关闭关联对象即时加载以提高性能 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指 定),不会加载关联表的所有字段,以提高性能 --> <setting name="aggressiveLazyLoading" value="false" /> <!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 --> <setting name="multipleResultSetsEnabled" value="true" /> <!-- 允许使用列标签代替列名 --> <setting name="useColumnLabel" value="true" /> <!-- 允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖 --> <setting name="useGeneratedKeys" value="true" /> <!-- 给予被嵌套的resultMap以字段-属性的映射支持 --> <setting name="autoMappingBehavior" value="FULL" /> <!-- 对于批量更新操作缓存SQL以提高性能 --> <setting name="defaultExecutorType" value="BATCH" /> <!-- 数据库超过25000秒仍未响应则超时 --> <setting name="defaultStatementTimeout" value="25000" />
......
typeHandlers用来自定义映射规则,如你可以自定义将Character映射为varchar,plugins元素则放了一些拦截器接口,你可以继承他们并做一些切面的事情。更多配置如如properties,objectFactory等,可以参考ibatis-3-config.dtd文档。
使用Spring时,不需要此配置文件,而是使用针对Spring的专门的配置文件(配置bean)。
初始化
1
2
3
4
5
6
7
8
9
10
11
12InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session=sqlSessionFactory .openSession(true); /** * 映射sql的标识字符串, * com.demo.mappers.personMapper是personMapper.xml文件中mapper标签的namespace属性的值, * getPerson是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL */ String statement = "com.demo.mappers.personMapper.getPerson";//映射sql的标识字符串 //执行查询返回一个唯一user对象的sql Person person = session.selectOne(statement, 1); System.out.println(person);
PersonMapper personMapper = session.getMapper(PersonMapper.class);
personMapper.insert(new Pserson(......));
......
session.commit();
session.close();
Configuration configuration = sessionManager.getConfiguration();
MapperRegistry mapperRegistry = configuration.getMapperRegistry();
if(!sessionManager.isManagedSessionStarted())
sessionManager.startManagedSession(true);
使用SqlSession类进行数据库操作
SqlSession接口提供了常用的数据库操作方法。所有的statement参数为xml文件中namespace加上sql语句id,如com.demo.mappers.PersonMapper.selectByPrimaryKey。
- <T> T selectOne(String statement);
- <T> T selectOne(String statement, Object parameter);
- <E> List<E> selectList(String statement);
- <E> List<E> selectList(String statement, Object parameter);
- <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
- <K, V> Map<K, V> selectMap(String statement, String mapKey);
- <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
- <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
- void select(String statement, Object parameter, ResultHandler handler);
- void select(String statement, ResultHandler handler);
- void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
- int insert(String statement);
- int insert(String statement, Object parameter);
- int update(String statement);
- int update(String statement, Object parameter);
- int delete(String statement);
- int delete(String statement, Object parameter);
以上这些方法只需要用到XML映射文件,不需要Mapper接口。
其他操作
- void commit();
- void commit(boolean force);
- void rollback();
- void rollback(boolean force);
- List<BatchResult> flushStatements();
- void close();
- void clearCache();
- Configuration getConfiguration();
- Connection getConnection();
- <T> T getMapper(Class<T> type);
通过Mapper实例操作数据库
可以同过SqlSession生成Mapper类实例,通过Mapper实例调用Mapper中定义的各种数据库操作方法。
1
2PersonMapper mapper = sqlSession.getMapper(PersonMapper.class); Person p=mapper.selectByPrimaryKey(1);
......
通过注解的方式定义数据库操作方法
可以直接在生成的Mapper类中额外加入自定义的数据库操作方法。使用注解可以没有XML映射文件。
1
2
3
4
5@Select("select * from person where name like #{name}") public Person selectPersonByName(String name); @Select("select * from person where content is not null") public List<Person> selectPersonWithContent();
注解详解
注解Mapper示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33@CacheNamespace(size = 512) public interface TestMapper { @SelectProvider(type = TestSqlProvider.class, method = "getSql") @Options(useCache = true, flushCache = false, timeout = 10000) @Results(value = { @Result(id = true, property = "id", column = "test_id", javaType = String.class, jdbcType = JdbcType.VARCHAR), @Result(property = "testText", column = "test_text", javaType = String.class, jdbcType = JdbcType.VARCHAR) }) public TestBean get(@Param("id") String id); @SelectProvider(type = TestSqlProvider.class, method = "getAllSql") @Options(useCache = true, flushCache = false, timeout = 10000) @Results(value = { @Result(id = true, property = "id", column = "test_id", javaType = String.class, jdbcType = JdbcType.VARCHAR), @Result(property = "testText", column = "test_text", javaType = String.class, jdbcType = JdbcType.VARCHAR) }) public List<TestBean> getAll(); @SelectProvider(type = TestSqlProvider.class, method = "getByTestTextSql") @Options(useCache = true, flushCache = false, timeout = 10000) @ResultMap(value = "getByTestText") public List<TestBean> getByTestText(@Param("testText") String testText); @InsertProvider(type = TestSqlProvider.class, method = "insertSql") @Options(flushCache = true, timeout = 20000) public void insert(@Param("testBean") TestBean testBean); @UpdateProvider(type = TestSqlProvider.class, method = "updateSql") @Options(flushCache = true, timeout = 20000) public void update(@Param("testBean") TestBean testBean); @DeleteProvider(type = TestSqlProvider.class, method = "deleteSql") @Options(flushCache = true, timeout = 20000) public void delete(@Param("id") String id); }
注解说明
- @CacheNamespace(size = 512) 定义在该命名空间内允许使用内置缓存,最大值为512个对象引用,读写默认是开启的,缓存内省刷新时间为默认3600000毫秒,写策略是拷贝整个对象镜像到全新堆(如同CopyOnWriteList)因此线程安全。
- @SelectProvider(type = TestSqlProvider.class, method = "getSql") : 提供查询的SQL语句,如果你不用这个注解,你也可以直接使用@Select("select * from ....")注解,把查询SQL抽取到一个类里面,方便管理,同时复杂的SQL也容易操作,type = TestSqlProvider.class就是存放SQL语句的类,而method = "getSql"表示get接口方法需要到TestSqlProvider类的getSql方法中获取SQL语句。
- @Options(useCache = true, flushCache = false, timeout = 10000) : 一些查询的选项开关,比如useCache = true表示本次查询结果被缓存以提高下次查询速度,flushCache = false表示下次查询时不刷新缓存,timeout = 10000表示查询结果缓存10000秒。更新数据库的操作,需要重新刷新缓存flushCache = true使缓存同步
- @Results(value = { @Result(id = true, property = "id", column = "test_id", javaType = String.class, jdbcType = JdbcType.VARCHAR), @Result(property = "testText", column = "test_text", javaType = String.class, jdbcType = JdbcType.VARCHAR) }) : 表示sql查询返回的结果集,@Results是以@Result为元素的数组,@Result表示单条属性-字段的映射关系,如:@Result(id = true, property = "id", column = "test_id", javaType = String.class, jdbcType = JdbcType.VARCHAR)可以简写为:@Result(id = true, property = "id", column = "test_id"),id = true表示这个test_id字段是个PK,查询时mybatis会给予必要的优化,应该说数组中所有的@Result组成了单个记录的映射关系,而@Results则单个记录的集合。
- @Param("paramName") :全局限定别名,定义查询参数在sql语句中的位置不再是顺序下标0,1,2,3....的形式,而是对应名称,该名称就在这里定义。 如果参数类型为模型类,要在sql中引用对象里面的属性,使用类似paramName.id,paramName.textText的形式,mybatis会通过反射找到这些属性值。
- @ResultMap(value = "getByTestText") :重要的注解,可以解决复杂的映射关系,包括resultMap嵌套,鉴别器discriminator等等。注意一旦你启用该注解,你将不得不在你的映射文件中配置你的resultMap,而value = "getByTestText"即为映射文件中的resultMap ID(注意此处的value = "getByTestText",必须是在映射文件中指定命名空间路径)。@ResultMap在某些简单场合可以用@Results代替,但是复杂查询,比如联合、嵌套查询@ResultMap就会显得解耦方便更容易管理。 映射文件示例如下,文件中的namespace路径必须是使用@resultMap的类路径,此处是TestMapper,文件中 id="getByTestText"必须和@resultMap中的value = "getByTestText"保持一致。@ResultMap("mapper_namespace.resultMap_id")
1
2
3
4
5
6
7
8
9
10
11<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <mapper namespace="com.wotao.taotao.persist.test.mapper.TestMapper"> <resultMap id="getByTestText" type="TestBean"> <id property="id" column="test_id" javaType="string" jdbcType="VARCHAR" /> <result property="testText" column="test_text" javaType="string" jdbcType="VARCHAR" /> </resultMap> </mapper>
- @InsertProvider(type = TestSqlProvider.class, method = "insertSql") :用法和含义@SelectProvider一样,只不过是用来插入数据库而用的。
- @UpdateProvider(type = TestSqlProvider.class, method = "updateSql") :用法和含义@SelectProvider一样,只不过是用来更新数据库而用的。
- @DeleteProvider(type = TestSqlProvider.class, method = "deleteSql") :用法和含义@SelectProvider一样,只不过是用来删除数据而用的。
Java映射文件
使用注解后,可以不再用XML映射文件编写SQL,而是在java类中编写。示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54public class TestSqlProvider { private static final String TABLE_NAME = "test"; public String getSql(Map<String, Object> parameters) { String uid = (String) parameters.get("id"); BEGIN(); SELECT("test_id, test_text"); FROM(TABLE_NAME); if (uid != null) { WHERE("test_id = #{id,javaType=string,jdbcType=VARCHAR}"); } return SQL(); } public String getAllSql() { BEGIN(); SELECT("test_id, test_text"); FROM(TABLE_NAME); return SQL(); } public String getByTestTextSql(Map<String, Object> parameters) { String tText = (String) parameters.get("testText"); BEGIN(); SELECT("test_id, test_text"); FROM(TABLE_NAME); if (tText != null) { WHERE("test_text like #{testText,javaType=string,jdbcType=VARCHAR}"); } return SQL(); } public String insertSql() { BEGIN(); INSERT_INTO(TABLE_NAME); VALUES("test_id", "#{testBean.id,javaType=string,jdbcType=VARCHAR}"); VALUES("test_text", "#{testBean.testText,javaType=string,jdbcType=VARCHAR}"); return SQL(); } public String updateSql() { BEGIN(); UPDATE(TABLE_NAME); SET("test_text = #{testBean.testText,javaType=string,jdbcType=VARCHAR}"); WHERE("test_id = #{testBean.id,javaType=string,jdbcType=VARCHAR}"); return SQL(); } public String deleteSql() { BEGIN(); DELETE_FROM(TABLE_NAME); WHERE("test_id = #{id,javaType=string,jdbcType=VARCHAR}"); return SQL(); } }
SqlBuilder和SelectBuilder
mybatis提供SelectBuilder和SqlBuilder这2个小工具来帮助我们生成SQL语句。SelectBuilder专门用来生成select语句,而SqlBuilder则是一般性的工具,可以生成任何SQL语句。可通过import static org.apache.ibatis.jdbc.SqlBuilder.BEGIN的方式引入SqlBuilder提供的静态方法。
- BEGIN()方法表示刷新本地线程,某些变量为了线程安全,会先在本地存放变量,此处需要刷新。
- SELECT,FROM,WHERE等方法拼凑sql字符串
- SQL()方法将返回最终append结束的字符串
- 更复杂的标签还有JOIN,INNER_JOIN,GROUP_BY,ORDER_BY等
参数
通过Map<String, Object> parameters接收Mapper接口中定义的参数。Mapper接口方法中定义使用了命名的参数如@Param("testId"),@Param("testText"),Map中的key为参数名,如果参数没有命名,key为基于0的顺序下标。
在Spring中使用
1
2
3
4
5
6
7
8
9@Repository("testBaseDAO") public class TestBaseDAO { ...... @Autowired public void setTestMapper(@Qualifier("testMapper") TestMapper testMapper) { this.testMapper = testMapper; } ...... }
关联查询
模型|数据表
Clazz
int id | int c_id |
String name | varchar c_name |
Teacher teacher | int teacher_id |
List<Student> students |
Teacher
int id | int t_id |
String name | varchar t_name |
Student
int id | int s_id |
String name | varchar s_name |
int class_id |
一对一关系(A实体类中有一个B实体类的属性 )
使用association标签,可用属性:
- property 对象属性名
- javaType 对象属性类型
- column 对应外键字段名称
- select 使用另一个查询封装的结果
方式一:嵌套结果
1
2
3
4
5
6
7
8
9
10
11
12<select id="getClazz" parameterType="int" resultMap="ClazzResultMap"> select * from Clazz c, Teacher t where c.teacher_id=t.t_id and c.c_id=#{id} </select> <!-- 使用resultMap映射实体类和字段之间的一一对应关系 --> <resultMap type="com.demo.models.Clazz" id="ClassResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" javaType="com.demo.models.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> </resultMap>
方式二:嵌套查询
1
2
3
4
5
6
7
8
9
10
11
12<select id="getClazz" parameterType="int" resultMap="ClazzResultMap"> select * from Clazz where c_id=#{id} </select> <!-- 使用resultMap映射实体类和字段之间的一一对应关系 --> <resultMap type="com.demo.Clazz" id="ClazzResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="refB" column="teacher_id" select="getTeacher"/> </resultMap> <select id="getTeacher" parameterType="int" resultType="com.demo.Teacher"> SELECT t_id id, t_name name FROM Teacher WHERE t_id=#{id} </select>
一对多关联(A实体类中有一个B实体类的集合)
使用collection标签
- ofType 集合中元素对象类型
方式一:嵌套结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<select id="getClazz" parameterType="int" resultMap="ClazzResultMap"> select * from Class c, Teacher t, Student s where c.teacher_id=t.t_id and c.c_id=s.c_id and c.c_id=#{id} </select> <resultMap type="com.demo.Clazz" id="ClazzResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" column="teacher_id" javaType="com.demo.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> <!-- ofType指定students集合中的对象类型 --> <collection property="students" ofType="com.demo.Student"> <id property="id" column="s_id"/> <result property="name" column="s_name"/> </collection> </resultMap>
方式二:嵌套查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<select id="getClazz" parameterType="int" resultMap="ClazzResultMap"> select * from class where c_id=#{id} </select> <resultMap type="com.demo.Clazz" id="ClazzResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" column="teacher_id" javaType="com.demo.Teacher" select="getTeacher"></association> <collection property="students" ofType="com.demo.Student" column="c_id" select="getStudent"></collection> </resultMap> <select id="getTeacher" parameterType="int" resultType="com.demo.Teacher"> SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id} </select> <select id="getStudent" parameterType="int" resultType="com.demo.Student"> SELECT s_id id, s_name name FROM student WHERE class_id=#{id} </select>
调用存储过程
定义存储过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17-- 创建存储过程(查询得到男性或女性的数量, 如果传入的是0就女性否则是男性) DELIMITER $ CREATE PROCEDURE mybatis.ges_user_count(IN sex_id INT, OUT user_count INT) BEGIN IF sex_id=0 THEN SELECT COUNT(*) FROM mybatis.p_user WHERE p_user.sex='女' INTO user_count; ELSE SELECT COUNT(*) FROM mybatis.p_user WHERE p_user.sex='男' INTO user_count; END IF; END $ -- 调用存储过程 DELIMITER ; SET @user_count = 0; CALL mybatis.ges_user_count(1, @user_count); SELECT @user_count;
sql映射配置
1
2
3
4
5
6
7
8<!-- 查询得到男性或女性的数量, 如果传入的是0就女性否则是男性 --> <select id="getUserCount" parameterMap="getUserCountMap" statementType="CALLABLE"> CALL mybatis.ges_user_count(?,?) </select> <parameterMap type="java.util.Map" id="getUserCountMap"> <parameter property="sexid" mode="IN" jdbcType="INTEGER"/> <parameter property="usercount" mode="OUT" jdbcType="INTEGER"/> </parameterMap>
查询
1
2
3
4
5Map<String, Integer> parameterMap = new HashMap<String, Integer>(); parameterMap.put("sexid", 1); parameterMap.put("usercount", -1); sqlSession.selectOne("getUserCount", parameterMap); Integer result = parameterMap.get("usercount");
缓存
Mybatis同时提供了一级缓存和二级缓存的支持。
- 一级缓存:基于PerpetualCache的HashMap本地缓存,存储作用域为SqlSession,当SqlSession flush或close后,该Session的所有Cache会被清空。一级缓存默认开启。
- 二级缓存:默认也是采用PerpetualCache HashMap存储,作用域为Mapper(Namespace),可以自定义存储源,如Ehcache。
- 开启二级缓存,Mybatis配置中加入<cache/>元素可开启二级缓存。二级缓存从cache(mapper.xml中定义)中取得,需要调用session.commit(),数据才会放入chache中,二级缓存才有效。
- 缓存的数据更新机制为:当某作用域(一级缓存Session/二级缓存Namespaces)进行了C/U/D操作后,默认该作用域下所有select中的缓存会被clear。
- 映射语句文件中所有select语句都会被缓存,映射文件中所有insert,update,delete语句都会刷新缓存。
1
2
3
4
5<cache eviction="FIFO" <!--回收策略为先进先出,默认使用LRU算法(最近最少使用)--> flushInterval="60000" <!--自动刷新时间60s--> size="512" <!--可缓存512个引用对象,最大为1024--> readOnly="true"/> <!--只读-->
Mybatis3.x与Spring4.x整合
有3种常用的整合方式及关键配置
http://blog.csdn.net/bluesky5219/article/details/7066174
- 数据映射器(MapperFactoryBean),可不用写映射文件,全采用注解方式提供sql语句和输入参数。
1
2
3
4
5<!--创建数据映射器,数据映射器必须为接口--> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.xxt.ibatis.dbcp.dao.UserMapper" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>
- 采用SqlSession的实现类SqlSessionTemplate。Mybatis-Spring中可用SqlSessionFactoryBean代替SqlSessionFactoryBuilder创建sessionFactory。
1
2
3
4
5
6
7<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 指定sqlMapConfig总配置文件,订制的environment在spring容器中不在生效--> <property name="configLocation" value="classpath:sqlMapConfig.xml"/> <!--指定实体类映射文件,可以指定同时指定某一包以及子包下面的所有配置文件,mapperLocations和configLocation有一个即可,当需要为实体类指定别名时,可指定configLocation属性,再在mybatis总配置文件中采用mapper引入实体类映射文件 --> <property name="mapperLocations" value="classpath*:com/xxt/ibatis/dbcp/**/*.xml"/> </bean>
- 采用抽象类org.mybatis.spring.support.SqlSessionDaoSupport提供SqlSession
1
2
3<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean>
-------------------
mybatis相关依赖
- mybatis
- mybatis-spring
- Spring相关依赖
spring-mybatis.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- 配置数据源 --> <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${jdbc_url}" /> <property name="username" value="${jdbc_username}" /> <property name="password" value="${jdbc_password}" /> ...... </bean> <!-- 配置Mybatis sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 实例化sqlSessionFactory时需要使用上述配置好的数据源 --> <property name="dataSource" ref="dataSource" /> <!-- 自动扫描me/gacl/mapping/目录下的所有SQL映射xml文件, 无需Configuration.xml里的手工配置--> <property name="mapperLocations" value="classpath:com/demo/mappers/*.xml" />
<!-- <property name="configLocation" value="classpath:configuration.xml" /> -->
</bean>
<!-- 配置Mybatis Mapper映射接口扫描器 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 扫描com.demo.mappers包以及它的子包下的所有映射接口 --> <property name="basePackage" value="com.demo.mappers" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean>
<!-- 另一种配置方式:data OR mapping interface,此处忽略-->
<!--<bean id="testMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="testSqlSessionFactory" />
<property name="mapperInterface" value="com.wotao.taotao.persist.test.mapper.TestMapper" />
</bean> -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28<!-- 配置Spring的事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 注解方式配置事务 --> <!-- <tx:annotation-driven transaction-manager="transactionManager" /> --> <!-- 拦截器方式配置事务 --> <tx:advice id="transactionAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" /> <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" /> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="find*" propagation="SUPPORTS" /> <tx:method name="get*" propagation="SUPPORTS" /> <tx:method name="select*" propagation="SUPPORTS" /> <!-- <tx:method name="*" propagation="SUPPORTS" /> --> </tx:attributes> </tx:advice> <!--把事务控制在Service层 --> <aop:config> <!-- execution( public * com.demo.service.*.*(..) ) --> <aop:pointcut id="transactionPointcut" expression="execution(* com.demo.service..*Impl.*(..))" /> <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" /> </aop:config> </beans>
创建Service接口
1
2
3
4public interface PersonService { List<Person> getAllPerson(); }
创建Service实现类
1
2
3
4
5
6
7
8
9@Service("IdOfPersonService") //自动在DI容器中注册成Service组件 public class PersonServiceImpl implements PersonService { @Autowired PersonMapper personMapper; //dao依赖注入 @Override public List<User> getAllPerson() { return personMapper.selectByExampleWithBLOBs(null); } }
创建控制器类(不使用Spring Servlet进行分发控制)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17@WebServlet("/persons") //Servlet3.0提供的注解,将一个继承了HttpServlet类的普通java类标注为一个Servlet,不需要在web.xml中配置 public class PersonServlet extends HttpServlet
{ private PersonService personService; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{ //获取所有的用户信息 List<Person> persons = userService.getAllPersons(); request.setAttribute("persons", persons); request.getRequestDispatcher("/index.jsp").forward(request, response); } public void init() throws ServletException { //在Servlet初始化时获取Spring上下文对象(ApplicationContext) ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); //从ApplicationContext中获取userService userService = (UserServiceI) ac.getBean("IdOfPersonService"); } }
Spring注解的控制器(Web.xml中配置Spring Servlet,其中Spring分发控制)
1
2
3
4
5
6
7
8
9
10
11
12
13@Controller @RequestMapping("/persons") public class CaseResultAnalyzeController { @Autowried private PersonService personService; @RequestMapping public ModelAndView index() { ModelAndView mv=new ModelAndView(); mv.addObject("persons", personService.getAllPersons()); mv.setViewName("/index.jsp"); return mv; } }
更多配置
Mybatis配置文件和数据库连接配置分离
单独创建db.properties文件
1
2
3
4driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/testdb name=xxxx password=xxxx
mybatis 配置文件中引入db.properties文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<?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 resource="db.properties"/> <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="${name}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> ...... </configuration>
定义实体类别名
mybatis配置文件的configuration节点下加入typeAliases元素
1
2
3
4
5
6<typeAliases> <!-- 为单个类设置别名 --> <typeAlias type="com.demo.Person" alias="_Person"/> <!-- 为整个包下的类设置别名,默认的别名就是不带包名的类名 --> <package name="com.demo"/> </typeAliases>
然后在sql映射的XML中就可以使用别名代替model类名了
1
2
3<insert id="addUser" parameterType="_Person"> insert into person(id,name) values(#{id},#{name}) </insert>
模型类和数据表字段名不一致
方式一:
在Mapper的XML文件中使用resultMap元素定义映射关系。sql语句定义中引用映射关系。
1
2
3
4
5
6
7
8
9<resultMap type="com.demo.Person" id="personResultMap"> <!-- 主键字段映射 --> <id property="id" column="person_id"/> <!-- 非主键字段映射 --> <result property="name" column="person_no"/> </resultMap> <select id="selectPersonResult" parameterType="int" resultMap="personResultMap"> select * from person where person_id=#{id} </select>
方式二:
使用sql语句生成和模型对象属性名相同的字段别名
1
2
3<select id="selectOrder" parameterType="int" resultType="com.demo.Person"> select person_id id, person_name name from person where person_id=#{id} </select>
模糊查询判断参数非空
1
2
3<isNotEmpty prepend="and" property="name"> NAME like '%'||#name#||'%' </isNotEmpty>
这种方式无法走索引(走索引只限于like 'xxx%'的形式,%xxx和%xxx%都不行),也有说有时候会遇到检索不到数据的(参考)
参考文档
http://www.cnblogs.com/xdp-gacl/tag/MyBatis%E5%AD%A6%E4%B9%A0%E6%80%BB%E7%BB%93/
http://www.cnblogs.com/ibook360/archive/2012/07/16/2594056.html
http://www.cnblogs.com/fsjohnhuang/category/618850.html (MyBatis魔法堂)
------------------------
从Ibatis过渡到Mybatis-比较Mybaits较与Ibatis有哪些方面的改进
1.全局文件的配置
MyBatis 全局配置文件的各主要元素基本和 iBatis 相同,只是在用法和个别名称上做了调整。
DTD 约束不同
MyBatis 的 DTD 文件已经包含在发布包下的 mybatis-3.0.x.jar 包中。iBatis 配置文件的根元素是 <sqlMapConfig>,MyBatis 使用的是 <configuration>。
1
2
3
4
5<?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> ...... </configuration>
SqlSessionFactory代替SqlMapClient
MyBatis 能够根据配置信息和数据库建立连接,并应用给定的连接池信息和事务属性。MyBatis 封装了这些操作,最终暴露一个 SqlSessionFactory 实例供开发者使用,从名字可以看出来,这是一个创建 SqlSession 的工厂类,通过 SqlSession 实例,开发者能够直接进行业务逻辑的操作,而不需要重复编写 JDBC 相关的样板代码。根据全局配置文件生成 SqlSession 的代码如下:
1
2
3
4Reader reader = Resources.getResourceAsReader("Configuration.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); SqlSession sqlSession = sqlSessionFactory.openSession();
Resources 是 MyBatis 提供的一个工具类,它用于简化资源文件的加载,它可以访问各种路径的文件。Mybatis现在已经没有SqlMapClient了,使用的则是SqlSession.在原来的基础上加了像selectMap,selectList,selectOne这样的方法,使用更方便了。
事务管理器和数据源配置方式
ibatis配置事务管理器和数据源的方式如下:
1
2
3
4
5
6<transactionManager type="JDBC" > <dataSource type="SIMPLE"> <property name="JDBC.Driver" value="${driver}"/> <!-- 其他数据源信息省略 --> </dataSource> </transactionManager>
在MyBatis中配置事务管理器和数据源的方式:
1
2
3
4
5
6
7
8
9<environments default="demo"> <environment id="demo"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="JDBC.Driver" value="${driver}"/> <!-- 其他数据源信息省略 --> </dataSource> </environment> </environments>
指定映射文件方式
在 iBatis 中指定映射文件的方式如下:
1
2
3<sqlMap resource=... /> <sqlMap resource=... /> <sqlMap resource=... />
在 MyBatis 中指定映射文件的方式:
1
2
3
4<mappers> <mapper resource=... /> <mapper resource=... /> </mappers>
MyBatis可以通过代码进行配置
1
2
3
4
5
6DataSource ds = …… // 获取一个 DataSource TransactionFactory txFactory = new JdbcTransactionFactory(); Environment env = new Environment("demo", txFactory, ds); Configuration cfg = new Configuration(env); cfg.addMapper(UserInfoMapper.class); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfg);
结合前面的配置文件,很容易理解这段代码的意思,不过,需要注意的是 Configuration 的 addMapper() 方法,该方法的参数通常是一个接口,可以在接口里面定义若干方法,在方法上使用注解来指定映射的 SQL 语句。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 映射 SQL 绑定接口 public interface UserInfoMapper { @Select("select * from userinfo where userid = #{userid}") public UserInfo getUserInfo(int userid); } // 接口绑定对应的数据访问方法 try { //UserInfo userinfo = (UserInfo) sqlSession.selectOne ("mybatis.demo.UserInfoMapper.selectUser", 2); UserInfoMapper userinfoMapper = sqlSession.getMapper(UserInfoMapper.class); UserInfo userinfo = userinfoMapper.getUserInfo(1); System.out.println(userinfo); } finally { sqlSession.close(); }
2.映射文件中配置 SQL 语句:
1
2
3
4
5
6
7
8
9<?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="mybatis.demo.UserInfoMapper"> <select id="selectUser" parameterType="int" resultType="mybatis.demo.UserInfo"> select * from UserInfo where userid =#{userid} </select> </mapper>
在 iBatis 中,namespace 不是必需的,且它的存在没有实际的意义。在 MyBatis 中,namespace 终于派上用场了,它使得映射文件与接口绑定变得非常自然。Ibatis用的parameterClass在mybatis中已经永不了了,mybatis里应该使用parameterType。另外resultMap里面也不能继续使用了改成了type。
同时数据类型的声明和ibatis有了很大的差别,ibatis可以像下面这样写
1
2
3insert into M_HEALTHSPECIALYTYPE(FCODE,FCHARGE,FTYPECONTENT,FID,FMARK) values (#FCODE:VARCHAR2#,#FCHARGE:VARCHAR2#,#FTYPECONTENT:VARCHAR2#,#FID#,#FMARK:VARCHAR2#)
而在mybatis的话一般是这样弄的:
1
2insert into M_HEALTHSPECIALYTYPE(FCODE,FCHARGE,FTYPECONTENT,FID,FMARK) values (#{FCODE,jdbcType=VARCHAR},#{FCHARGE,jdbcType=VARCHAR},#{FTYPECONTENT,jdbcType=VARCHAR},#{FID},#{FMARK,jdbcType=VARCHAR})
针对映射文件,首先是一系列的属性名称的改变,这些仅仅是名称的改变,用法和含义并没有发生变化:
· 和全局配置文件一样,由于 DTD 约束发生变化,根元素也由原来的 <sqlMap> 调整为 <mapper>。
· <select> 等元素的 parameterClass 属性改为了 parameterType 属性。
· <select> 等元素的 resultClasss 属性改为了 resultType 属性。
· <parameterMap> 等元素的 class 属性改为了 type 属性。
· <result> 元素的 columnIndex 属性被移除了。
· 嵌套参数由 #value# 改为了 #{value}。
· <parameter> 等元素的 jdbcType 属性取值中,原来的 "ORACLECURSOR" 取值改为了现在的 "CURSOR","NUMBER" 取值改为了 "NUMERIC"。
3.使用 SqlSession 执行映射文件中配置的 SQL 语句
1
2
3
4
5
6
7
8
9try { UserInfo userinfo = (UserInfo) sqlSession.selectOne ("mybatis.demo.UserInfoMapper.getUser", 2); System.out.println(userinfo); } finally { sqlSession.close(); }
需要注意的是,SqlSession 的使用必需遵守上面的格式,即在 finally 块中将其关闭。以保证资源得到释放,防止出现内存泄露!以上就是一个简单而完整的 MyBatis 程序。其中涉及了全局配置文件,映射文件,构建 SqlSession 对象,执行数据访问操作等四个步骤。
4.iBatis/MyBatis 对存储过程的支持.
iBatis 中调用存储过程的方式(通过使用 <procedure> 元素进行存储过程的定义):
1
2
3<procedure id="getValues" parameterMap="getValuesPM"> { ? = call pkgExample.getValues(p_id => ?) } </procedure>
在 MyBatis 中,<proccedure> 元素已经被移除,通过 <select>、<insert> 和 <update> 进行定义:
1
2
3
4<select id="getValues" parameterMap="getValuesPM" statementType="CALLABLE"> { ? = call pkgExample.getValues(p_id => ?)} </select>
如上所示,通过 statementType 属性将该语句标识为存储过程而非普通 SQL 语句。
总结:
通过前面的示例可以看出,MyBatis 在编码中的最大的改变就是将一个最常用的 API 由 SqlMapClient 改为SqlSessionFactory。另外,类型处理器接口也由原来的 TypeHandlerCallback 改为了 TypeHandler。最后 DataSourceFactory 也进行了调整,移动到 org.apache.ibatis.datasource 包下,其中的方法也作了微调。总之,代码层面公开的部分改动较少,不会给开发者造成较大的移植成本。
转载于:https://www.cnblogs.com/pixy/p/5038275.html
最后
以上就是耍酷耳机最近收集整理的关于MyBatis使用总结 从Ibatis过渡到Mybatis-比较Mybaits较与Ibatis有哪些方面的改进的全部内容,更多相关MyBatis使用总结 从Ibatis过渡到Mybatis-比较Mybaits较与Ibatis有哪些方面内容请搜索靠谱客的其他文章。
发表评论 取消回复