MyBatis

MyBatis
博客分类: OpenSource

MyBatis示例MyBatis动态SQLMyBatis和Hibernate的比较 .

一、MyBatis简介
1. MyBatis概念
MyBatis本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。它支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。

2. MyBatis和Hibernate比较
1)hibernate是全自动,而mybatis是半自动。hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。而mybatis仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写sql来实现和管理。
2)hibernate数据库移植性远大于mybatis。hibernate通过它强大的映射结构和hql语言,大大降低了对象与数据库(oracle、mysql等)的耦合性,而mybatis由于需要手写sql,因此与数据库的耦合性直接取决于程序员写sql的方法,如果sql不具通用性而用了很多某数据库特性的sql语句的话,移植性也会随之降低很多,成本很高。
3)hibernate拥有完整的日志系统,mybatis则欠缺一些。hibernate日志系统非常健全,涉及广泛,包括:sql记录、关系异常、优化警告、缓存提示、脏数据警告等;而mybatis则除了基本记录功能外,功能薄弱很多。
4)mybatis相比hibernate需要关心很多细节。hibernate配置要比mybatis复杂的多,学习成本也比mybatis高。但也正因为mybatis使用简单,才导致它要比hibernate关心很多技术细节。mybatis由于不用考虑很多细节,开发模式上与传统jdbc区别很小,因此很容易上手并开发项目,但忽略细节会导致项目前期bug较多,因而开发出相对稳定的软件很慢,而开发出软件却很快。hibernate则正好与之相反。但是如果使用hibernate很熟练的话,实际上开发效率丝毫不差于甚至超越mybatis。
5)sql直接优化上,mybatis要比hibernate方便很多。由于mybatis的sql都是写在xml里,因此优化sql比hibernate方便很多。而hibernate的sql很多都是自动生成的,无法直接维护sql;虽有hql,但功能还是不及sql强大,见到报表等变态需求时,hql也歇菜,也就是说hql是有局限的;hibernate虽然也支持原生sql,但开发模式上却与orm不同,需要转换思维,因此使用上不是非常方便。总之写sql的灵活度上hibernate不及mybatis。
6)Hibernate有更好的二级缓存机制,可以使用第三方缓存。而MyBatis的二级缓存机制不佳。

二、MyBatis简单示例
1. 导包
新建一个Java项目,将 mybatis-3.1.1.jar 和 mysql-connector-java-5.1.6.jar 导入即可。

2. src/Configuration.xml配置文件
Configuration.xml是mybatis用来建立 sessionFactory 用的,里面主要包含了数据库连接相关东西,还有java类所对应的别名,比如<typeAlias alias="User" type="com.jiang.mybatis.model.User"/>这个别名非常重要,你在具体的类的映射中,比如User.xml 中resultType就是对应这里的。要保持一致,当然这里的resultType还有另外单独的定义方式,后面再说。里面的<mapper resource="com/jiang/mybatis/model/User.xml"/>是包含要映射的类的xml配置文件。


Java代码 复制代码 收藏代码
1.<?xml version="1.0" encoding="UTF-8" ?>
2.<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
3."http://mybatis.org/dtd/mybatis-3-config.dtd">
4.<configuration>
5. <typeAliases>
6. <typeAlias alias="User" type="com.jiang.mybatis.model.User"/>
7. </typeAliases>
8.
9. <environments default="development">
10. <environment id="development">
11. <transactionManager type="JDBC"/>
12. <dataSource type="POOLED">
13. <property name="driver" value="com.mysql.jdbc.Driver"/>
14. <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
15. <property name="username" value="root"/>
16. <property name="password" value="1234"/>
17. </dataSource>
18. </environment>
19. </environments>
20.
21. <mappers>
22. <mapper resource="com/jiang/mybatis/model/User.xml"/>
23. </mappers>
24.</configuration>


3. User.java实体


Java代码 复制代码 收藏代码
1.package com.jiang.mybatis.model;
2.
3.public class User {
4.
5. private int id;
6. private String userName;
7. private String userAge;
8. private String userAddress;
9.
10. public int getId() {
11. return id;
12. }
13. public void setId(int id) {
14. this.id = id;
15. }
16. public String getUserName() {
17. return userName;
18. }
19. public void setUserName(String userName) {
20. this.userName = userName;
21. }
22. public String getUserAge() {
23. return userAge;
24. }
25. public void setUserAge(String userAge) {
26. this.userAge = userAge;
27. }
28. public String getUserAddress() {
29. return userAddress;
30. }
31. public void setUserAddress(String userAddress) {
32. this.userAddress = userAddress;
33. }
34.}


4. User.xml映射文件


Java代码 复制代码 收藏代码
1.<?xml version="1.0" encoding="UTF-8" ?>
2.<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3."http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4.
5.<mapper namespace="com.jiang.mybatis.models.UserMapper">
6. <!-- 注意:此处resultType的User为Configuration里的别名。
7. 实体的属性和数据库中的字段名相同时会自动匹配,如果不同则需要配置一个自己的resultMap然后指定一个返回类型为resultMap的自定义Map -->
8. <select id="selectUserByID" parameterType="int" resultType="User">
9. select * from user where id = #{id}
10. </select>
11.</mapper>


5. 测试


Java代码 复制代码 收藏代码
1.package test;
2.
3.import java.io.Reader;
4.import org.apache.ibatis.io.Resources;
5.import org.apache.ibatis.session.SqlSession;
6.import org.apache.ibatis.session.SqlSessionFactory;
7.import org.apache.ibatis.session.SqlSessionFactoryBuilder;
8.import com.jiang.mybatis.model.User;
9.
10.public class Test {
11. private static SqlSessionFactory sqlSessionFactory;
12. private static Reader reader;
13. static {
14. try {
15. reader = Resources.getResourceAsReader("Configuration.xml");
16. sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
17. } catch (Exception e) {
18. e.printStackTrace();
19. }
20. }
21. public static SqlSessionFactory getSession() {
22. return sqlSessionFactory;
23. }
24. public static void main(String[] args) {
25. SqlSession session = sqlSessionFactory.openSession();
26. try {
27. User user = (User) session.selectOne(
28. "com.jiang.mybatis.models.UserMapper.selectUserByID", 1);
29. System.out.println(user.getUserAddress());
30. System.out.println(user.getUserName());
31. } finally {
32. session.close();
33. }
34. }
35.}


三、基于命名空间的接口方式编程
基于接口方式的编程有很多优点,首先它不是基于文字的,那就更安全了。第二,如果你的 IDE 有代码补全功能,那么你可以利用它来操纵已映射的 SQL 语句。第三,不需要强制类型转换,同时 IUserMapper接口可以保持简洁,返回值类型很安全(参数类型也很安全) 。

1. 新建接口类IUserOperation.java


Java代码 复制代码 收藏代码
1.package com.jiang.mybatis.inter;
2.import com.jiang.mybatis.model.User;
3.public interface IUserOperation {
4. //这里的方法名必须和映射文件里的select的id相同
5. public User selectUserByID(int id);
6.}


2. 修改User.xml映射文件
<mapper namespace="com.jiang.mybatis.inter.IUserOperation">

3. 测试


Java代码 复制代码 收藏代码
1....
2.public static void main(String[] args) {
3. SqlSession session = sqlSessionFactory.openSession();
4. try {
5. IUserOperation userOperation = session.getMapper(IUserOperation.class);
6. User user = userOperation.selectUserByID(1);
7. System.out.println(user.getUserAddress());
8. System.out.println(user.getUserName());
9. } finally {
10. session.close();
11. }
12. }
13....


四、MyBatis实现增删改查
1. 命名空间接口IUserOperation.java


Java代码 复制代码 收藏代码
1.package com.jiang.mybatis.inter;
2.import java.util.List;
3.import com.jiang.mybatis.model.User;
4.public interface IUserOperation {
5. //这里的方法名必须和映射文件里的select的id相同
6. public User selectUserByID(int id);
7. public List<User> selectUsers(String userName);
8. public void addUser(User user);
9. public void updateUser(User user);
10. public void deleteUser(int id);
11.}


2. 映射文件User.xml


Java代码 复制代码 收藏代码
1.<?xml version="1.0" encoding="UTF-8" ?>
2.<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3."http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4.
5.<mapper namespace="com.jiang.mybatis.inter.IUserOperation">
6. <resultMap type="User" id="resultListUser">
7. <id column="id" property="id" />
8. <result column="user_name" property="userName" />
9. <result column="user_age" property="userAge" />
10. <result column="user_address" property="userAddress" />
11. </resultMap>
12.
13. <select id="selectUserByID" parameterType="int" resultMap="resultListUser">
14. select * from user where id = #{id}
15. </select>
16.
17. <!-- 返回list 的select 语句,注意 resultMap 的值是指向前面定义好的 -->
18. <select id="selectUsers" parameterType="string" resultMap="resultListUser">
19. select * from user where user_name like #{userName}
20. </select>
21.
22. <!--id和parameterType分别与IUserOperation接口中的addUser方法的名字和参数类型一致;
23. 以#{name}的形式引用User参数的属性,MyBatis将使用反射读取Student参数的此属性,#{name}中name大小写敏感;
24. seGeneratedKeys设置为"true"表明要MyBatis获取由数据库自动生成的主键;
25. keyProperty="id"指定把获取到的主键值注入到User的id属性-->
26. <insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
27. insert into user(user_name,user_age,user_address) values (#{userName},#{userAge},#{userAddress})
28. </insert>
29.
30. <update id="updateUser" parameterType="User" >
31. update user set user_name=#{userName},user_age=#{userAge},user_address=#{userAddress} where id=#{id}
32. </update>
33.
34. <delete id="deleteUser" parameterType="int">
35. delete from user where id=#{id}
36. </delete>
37.</mapper>


3. 测试


Java代码 复制代码 收藏代码
1.package test;
2.import java.io.Reader;
3.import java.util.List;
4.import org.apache.ibatis.io.Resources;
5.import org.apache.ibatis.session.SqlSession;
6.import org.apache.ibatis.session.SqlSessionFactory;
7.import org.apache.ibatis.session.SqlSessionFactoryBuilder;
8.import com.jiang.mybatis.inter.IUserOperation;
9.import com.jiang.mybatis.model.User;
10.public class Test {
11. private static SqlSessionFactory sqlSessionFactory;
12. private static Reader reader;
13. static {
14. try {
15. reader = Resources.getResourceAsReader("Configuration.xml");
16. sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
17. } catch (Exception e) {
18. e.printStackTrace();
19. }
20. }
21. public static void main(String[] args) {
22. Test test = new Test();
23. test.selectUserByID();
24. test.selectUsers();
25. test.addUser();
26. test.updateUser();
27. test.deleteUser();
28. }
29. public void selectUserByID() {
30. SqlSession session = sqlSessionFactory.openSession();
31. try {
32. IUserOperation userOperation = session.getMapper(IUserOperation.class);
33. User user = userOperation.selectUserByID(1);
34. System.out.println("selectUserByID: "+user.getUserAddress()+":"+user.getUserName());
35. } finally {
36. session.close();
37. }
38. }
39. public void selectUsers() {
40. SqlSession session = sqlSessionFactory.openSession();
41. try {
42. IUserOperation userOperation = session
43. .getMapper(IUserOperation.class);
44. List<User> users = userOperation.selectUsers("AAA");
45. for (User user : users) {
46. System.out.println("selectUsers: "+user.getId() + ":" + user.getUserName()
47. + ":" + user.getUserAddress());
48. }
49. } finally {
50. session.close();
51. }
52. }
53. public void addUser(){
54. User user=new User();
55. user.setUserAddress("人民广场");
56. user.setUserName("飞鸟");
57. user.setUserAge("33");
58. SqlSession session = sqlSessionFactory.openSession();
59. try {
60. IUserOperation userOperation=session.getMapper(IUserOperation.class);
61. userOperation.addUser(user);
62. session.commit(); //增加必须提交事务,否则不会写入库中。
63. System.out.println("addUser: id="+user.getId());
64. } finally {
65. session.close();
66. }
67. }
68. public void updateUser(){
69. //先得到用户,然后修改,提交。
70. SqlSession session = sqlSessionFactory.openSession();
71. try {
72. IUserOperation userOperation=session.getMapper(IUserOperation.class);
73. User user = userOperation.selectUserByID(1);
74. user.setUserAddress("MMMMMMMM");
75. userOperation.updateUser(user);
76. session.commit();
77. } finally {
78. session.close();
79. }
80. }
81. public void deleteUser(){
82. SqlSession session = sqlSessionFactory.openSession();
83. try {
84. IUserOperation userOperation=session.getMapper(IUserOperation.class);
85. userOperation.deleteUser(1);
86. session.commit();
87. } finally {
88. session.close();
89. }
90. }
91.}


五、MyBatis的关联查询
1. 增加实体Article.java


Java代码 复制代码 收藏代码
1.package com.jiang.mybatis.model;
2.public class Article {
3. private int id;
4. private User user;
5. private String title;
6. private String content;
7. ....
8.}


2. 命名空间接口IUserOperation.java
public List<Article> getArticlesByUser(int id);

3. 映射文件User.xml


Java代码 复制代码 收藏代码
1.<?xml version="1.0" encoding="UTF-8" ?>
2.<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3."http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4.
5.<mapper namespace="com.jiang.mybatis.inter.IUserOperation">
6. <resultMap type="User" id="resultListUser">
7. <id column="id" property="id" />
8. <result column="user_name" property="userName" />
9. <result column="user_age" property="userAge" />
10. <result column="user_address" property="userAddress" />
11. </resultMap>
12.
13. <resultMap id="resultUserArticleList" type="Article">
14. <id property="id" column="aid" />
15. <result property="title" column="title" />
16. <result property="content" column="content" />
17. <association property="user" javaType="User" resultMap="resultListUser" />
18. </resultMap>
19.
20. <sql id="Base_Column_List">
21. user.id,user.user_name,user.user_address,article.id aid,article.title,article.content
22. </sql>
23.
24. <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
25. select <include refid="Base_Column_List"/>
26. from user,article where user.id=article.userid and user.id=#{id}
27. </select>
28.</mapper>


4. 测试


Java代码 复制代码 收藏代码
1.public void getUserArticles(int userid){
2. SqlSession session = sqlSessionFactory.openSession();
3. try {
4. IUserOperation userOperation=session.getMapper(IUserOperation.class);
5. List<Article> articles = userOperation.getUserArticles(userid);
6. for(Article article:articles){
7. System.out.println(article.getTitle()+" : "+article.getUser().getUserName());
8. }
9. } finally {
10. session.close();
11. }
12.}


六、MyBatis的动态SQL
1. if标签
<if test="userName != null">
and user_name= #{userName}
</if>
如果userName不为null则加上if中的筛选条件

2. choose标签
<choose>
<when test="userAge != null">
and user_age = #{userAge}
</when>
<when test="userAddress != null">
and user_address= #{userAddress}
</when>
<otherwise>
and user_name = "userName"
</otherwise>
</choose>
choose标签跟switch效果一样,如果userAge不为null就增加该条件,然后退出。如果所有的when都为null,则执行otherwise中的筛选条件。

3. where标签
select * from t_blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="content != null">
and content = #{content}
</if>
</where>
where标签可以智能的处理SQL,如果标签里面的内容不全为null的话,它会自动在SQL里加入一个where语句,并且可以去掉条件中多余的AND或OR。

4. set标签
update t_blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="content != null">
content = #{content},
</if>
<if test="owner != null">
owner = #{owner}
</if>
</set>
set标签主要用于update语句,对SQL的处理和where标签一样。

5. trim标签
select * from t_blog
<trim prefix="where" prefixOverrides="and | or">
<if test="title != null">
title = #{title}
</if>
<if test="content != null">
and content = #{content}
</if>
<if test="owner != null">
or owner = #{owner}
</if>
</trim>
trim标签的作用和上面的where和set相似,如果里面条件不全为null,则加上prefix条件,并能自动去掉前面多余的and或or。
前缀prefix和后缀suffix分别对应的属性是prefixOverrides和suffixOverrides。

6. foreach标签
select * from t_news n where
<foreach collection="listTag" index="index" item="tag" open="(" separator="," close=")">
#{tag} in n.tags
</foreach>
select * from xxx where mid in
<foreach collection="mids" item="mid" open="(" separator="," close=")">
#{mid}
</foreach>
foreach标签的作用是循环的把collection指定的参数里的每个元素加入一个分支语句连接起来。标签的属性主要有 item,index,collection,open,separator,close。
collection应该是传入参数中的一个list或者数组或者map
item表示集合中每一个元素进行迭代时的别名
index指定每次迭代到的位置
open表示该语句以什么开始
separator表示在每次进行迭代之间以什么符号作为分隔符
close表示以什么结束
上面的标签转换为SQL为:
select * from xxx where mid in ( ? , ? ...)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值