MyBatis入门(一)—— 入门案例
一、MyBatis简介
MyBatis是面向sql的持久层框架,他封装了jdbc访问数据库的过程,我们开发,只需专注于sql语句本身的拼装,其它赋值的过程全部可以交给MyBatis去完成。
与Hibernate比较:
1.Hibernate学习门槛不低,要精通门槛更高。门槛高在怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate缓存与数据加载策略方面需要你的经验和能力都很强才行。国内目前前的情况精通hibernate技术大牛非常少。
2.sql优化方面,Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。当然了,Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。说得更深入一些,如果有个查询要关联多张表,比如5张表,10张表时,而且,我们要取的字段只是其中几张表的部分字段。这时用hibernate时就会显得非常力不从心。就算用hibernate的sqlquery,后续的维护工作也会让人发狂。
二、入门案例
1、数据库的准备(创表语句)
1 -- ----------------------------
2 -- Table structure for `user`
3 -- ----------------------------
4 DROP TABLE IF EXISTS `user`;
5 CREATE TABLE `user` (
6 `id` int(11) NOT NULL AUTO_INCREMENT,
7 `username` varchar(32) NOT NULL COMMENT '用户名称',
8 `birthday` date DEFAULT NULL COMMENT '生日',
9 `sex` char(1) DEFAULT NULL COMMENT '性别',
10 `address` varchar(256) DEFAULT NULL COMMENT '地址',
11 PRIMARY KEY (`id`)
12 ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
13
14 -- ----------------------------
15 -- Records of user
16 -- ----------------------------
17 INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
18 INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
19 INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
20 INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州');
21 INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
22 INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州');
23 INSERT INTO `user` VALUES ('26', '王五', null, null, null);
2、使用idea新建maven-archetype-quickstart项目
3、引入依赖
1 <dependency> 2 <groupId>mysql</groupId> 3 <artifactId>mysql-connector-java</artifactId> 4 <version>5.1.45</version> 5 </dependency> 6 <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> 7 <dependency> 8 <groupId>org.mybatis</groupId> 9 <artifactId>mybatis</artifactId> 10 <version>3.2.7</version> 11 </dependency>
4、于resources文件夹中创建SqlMapConfig.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 和spring整合后 environments配置将废除 --> 7 <environments default="development"> 8 <environment id="development"> 9 <!-- 使用jdbc事务管理 --> 10 <transactionManager type="JDBC" /> 11 <!-- 数据库连接池 --> 12 <dataSource type="POOLED"> 13 <property name="driver" value="com.mysql.jdbc.Driver" /> 14 <property name="url" 15 value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> 16 <property name="username" value="root" /> 17 <property name="password" value="" /> 18 </dataSource> 19 </environment> 20 </environments> 21 22 <mappers> 23 <!-- 第一种方式,加载 resource--> 24 <mapper resource="User.xml"></mapper> 25 <mapper resource="UserMapper.xml"/> 26 27 <!-- 第三种方式,包扫描器要求(推荐使用此方式): 28 1、映射文件与接口同一目录下 29 2、映射文件名必需与接口文件名称一致 30 --> 31 <!--<package name="com.cenobitor.mapper"/>--> 32 </mappers> 33 </configuration>
5、创建实体类User
1 package com.cenobitor.pojo;
2
3 import java.util.Date;
4
5 public class User {
6
7 private Integer id;
8 private String username;// 用户姓名
9 private String sex;// 性别
10 private Date birthday;// 生日
11 private String address;// 地址
12 private String uuid;
13
14 ......
15 }
6、配置SQL查询的映射文件(resources目录)
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <!-- namespace:命名空间,类似于java包,主要用于隔离sql语句的,后续有重要作用
6 #{}:占位符,相当于jdbc的?
7 ${}:字符串拼接指令,注意如果入参为普通数据类型时,括号里面只能写value
8 -->
9 <mapper namespace="user">
10 <!-- id:sql id标识sql语句的唯一标识
11 parameterType:入参的数据类型
12 resultType:返回结果的数据类型
13 -->
14 <select id="getUserById" parameterType="int" resultType="com.cenobitor.pojo.User">
15 SELECT
16 `id`,
17 `username`,
18 `birthday`,
19 `sex`,
20 `address`
21 FROM `user`
22 WHERE id = #{id}
23 </select>
24
25 <!-- resultType:如果返回结果是集合时,只需要设置为元素的数据类型就可 -->
26 <select id="getUserByName" parameterType="String" resultType="com.cenobitor.pojo.User">
27 SELECT
28 `id`,
29 `username`,
30 `birthday`,
31 `sex`,
32 `address`
33 FROM `user`
34 WHERE username LIKE '%${value}%'
35 </select>
36
37 <insert id="insertUser" parameterType="com.cenobitor.pojo.User">
38 INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
39 VALUES (#{username},#{birthday},#{sex},#{address})
40 </insert>
41
42 <!--返回MySql自增主键-->
43 <!-- useGeneratedKeys:标识插入使用自增id
44 keyProperty:与useGeneratedKeys配套使用,用于绑定主键接收的pojo属性
45 -->
46 <insert id="insertUserKey" parameterType="com.cenobitor.pojo.User"
47 useGeneratedKeys="true" keyProperty="id">
48
49 <!-- selectKey:用于配置主键返回
50 keyProperty:要绑定的pojo属性
51 resultType:属性数据类型
52 order:指定什么时候执行,AFTER之后
53 -->
54 <!-- <selectKey keyProperty="id" resultType="int" order="AFTER">
55 SELECT LAST_INSERT_ID()
56 </selectKey> -->
57
58 INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
59 VALUES (#{username},#{birthday},#{sex},#{address})
60 </insert>
61
62 <!--返回MySql的uuid返回主键-->
63 <insert id="insertUserUUID" parameterType="com.cenobitor.pojo.User">
64
65 <!-- selectKey:用于配置主键返回
66 keyProperty:要绑定的pojo属性
67 resultType:属性数据类型
68 order:指定什么时候执行,AFTER之后
69 -->
70 <selectKey keyProperty="uuid" resultType="String" order="BEFORE">
71 SELECT UUID()
72 </selectKey>
73
74 INSERT INTO USER (`username`,`birthday`,`sex`,`address`,`uuid`)
75 VALUES (#{username},#{birthday},#{sex},#{address},#{uuid})
76 </insert>
77
78 <update id="updateUser" parameterType="com.cenobitor.pojo.User">
79 UPDATE USER SET username = #{username} WHERE id = #{id}
80 </update>
81
82 <delete id="deleteUser" parameterType="com.cenobitor.pojo.User">
83 DELETE FROM `user` WHERE `id` = #{id}
84 </delete>
85
86 </mapper>
7、加载映射文件,在SqlMapConfig.xml配置mappers节点
8、编写测试类
1 package com.cenobitor;
2
3 import com.cenobitor.Utils.SqlSessionFactoryUtils;
4 import com.cenobitor.pojo.User;
5 import junit.framework.Test;
6 import junit.framework.TestCase;
7 import junit.framework.TestSuite;
8 import org.apache.ibatis.io.Resources;
9 import org.apache.ibatis.session.SqlSession;
10 import org.apache.ibatis.session.SqlSessionFactory;
11 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
12
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.util.Date;
16 import java.util.List;
17
18 /**
19 * Unit test for simple App.
20 */
21 public class AppTest extends TestCase {
22 //根据id查找用户
23 public void testGetUserById() throws IOException {
24
25 //创建SqlSessionFactoryBuilder对象
26 SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
27 //查找配置文件,创建输入流
28 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
29 //加载配置文件,创建SqlSessionFactory
30 SqlSessionFactory sqlSessionFactory = sfb.build(inputStream);
31 //创建SqlSession
32 SqlSession sqlSession = sqlSessionFactory.openSession();
33 //执行查询,参数一:要查询的statementId,参数二:sql语句入参
34 User user = sqlSession.selectOne("user.getUserById", 1);
35 //输入查询结果
36 System.out.println(user);
37
38 //释放资源
39 sqlSession.close();
40 }
41
42 //根据用户名查找用户列表
43 public void testGetUserByName(){
44 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
45 SqlSession sqlSession = sqlSessionFactory.openSession();
46 List<User> list = sqlSession.selectList("user.getUserByName", "张");
47 for (User user : list) {
48 System.out.println(user);
49 }
50
51 sqlSession.close();
52 }
53
54 //插入用户
55 public void testInsertUser(){
56 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
57 SqlSession sqlSession = sqlSessionFactory.openSession();
58
59 User user = new User();
60 user.setUsername("貂蝉");
61 user.setSex("0");
62 user.setBirthday(new Date());
63 user.setAddress("吕布");
64
65 //执行插入语句
66 sqlSession.insert("user.insertUser",user);
67 //提交事务
68 sqlSession.commit();
69 //释放资源
70 sqlSession.close();
71 }
72
73 //Mysql自增返回
74 public void testInsertUserKey(){
75 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
76 SqlSession sqlSession = sqlSessionFactory.openSession();
77
78 User user = new User();
79 user.setUsername("杨玉环");
80 user.setSex("0");
81 user.setBirthday(new Date());
82 user.setAddress("李隆基");
83
84 //执行插入语句
85 sqlSession.insert("user.insertUserKey", user);
86 System.out.println(user);
87 //提交事务
88 sqlSession.commit();
89 //释放资源
90 sqlSession.close();
91 }
92
93 //Mysql的uuid返回主键
94 //注:在使用uuid之前数据库user表要先加上uuid2字段、user的pojo也要加上相应属性
95 public void testInsertUserUUID(){
96 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
97 SqlSession sqlSession = sqlSessionFactory.openSession();
98
99 User user = new User();
100 user.setUsername("孙尚香");
101 user.setSex("0");
102 user.setBirthday(new Date());
103 user.setAddress("刘备");
104
105 //执行插入语句
106 sqlSession.insert("user.insertUserUUID", user);
107 System.out.println(user);
108 //提交事务
109 sqlSession.commit();
110 //释放资源
111 sqlSession.close();
112 }
113
114 //修改用户
115 public void testUpdateUser(){
116 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
117 SqlSession sqlSession = sqlSessionFactory.openSession();
118
119 User user = new User();
120 user.setUsername("吕雉");
121 user.setId(32);
122
123 //执行插入语句
124 sqlSession.update("user.updateUser",user);
125
126 //提交事务
127 sqlSession.commit();
128 //释放资源
129 sqlSession.close();
130 }
131
132 //删除用户
133 public void testDeleteUser(){
134 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
135 SqlSession sqlSession = sqlSessionFactory.openSession();
136 sqlSession.delete("user.deleteUser",32);
137 sqlSession.commit();
138 sqlSession.close();
139 }
140 }
9、抽取SqlSessionFactoryUtils工具类,共享SqlSessionFactory的对象
1 public class SqlSessionFactoryUtils {
2 private SqlSessionFactoryUtils(){}
3
4 private static class SqlSessionFactoryInstance{
5
6 public static SqlSessionFactory sqlSessionFactory;
7
8 static {
9 try {
10 sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml"));
11 } catch (IOException e) {
12 e.printStackTrace();
13 }
14 }
15 }
16
17 public static SqlSessionFactory getSqlSessionFactory(){
18 return SqlSessionFactoryInstance.sqlSessionFactory;
19 }
20
21 }
三、MyBatis架构图


四、MyBatis 动态代理Dao开发
1、开发规则
- namespace必须是接口的全路径名
- 接口的方法名必须与映射文件的sql id 一致
- 接口的输入参数必须与映射文件的parameterType类型一致
- 接口的返回类型必须与映射文件的resultType类型一致
2、动态代理Dao开发步骤
①创建UserMapper.xml映射文件
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="com.cenobitor.mapper.UserMapper">
6
7 <select id="getUserById" parameterType="int" resultType="com.cenobitor.pojo.User">
8 SELECT
9 `id`,
10 `username`,
11 `birthday`,
12 `sex`,
13 `address`
14 FROM `user`
15 WHERE id = #{id}
16 </select>
17
18 <select id="getUserByName" parameterType="String" resultType="com.cenobitor.pojo.User">
19 SELECT
20 `id`,
21 `username`,
22 `birthday`,
23 `sex`,
24 `address`
25 FROM `user`
26 WHERE username LIKE '%${value}%'
27 </select>
28
29 <insert id="insertUser" parameterType="com.cenobitor.pojo.User">
30 INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
31 VALUES (#{username},#{birthday},#{sex},#{address})
32 </insert>
33
34 </mapper>
②创建UserMapper接口
1 package com.cenobitor.mapper;
2
3 import com.cenobitor.pojo.User;
4 import java.util.List;
5
6 public interface UserMapper {
7
8 /**根据用户ID查询用户信息
9 * @param id
10 * @return
11 */
12 User getUserById(Integer id);
13
14 /**
15 * 根据用户名查找用户列表
16 * @param name
17 * @return
18 */
19 List<User> getUserByName(String name);
20
21 /**
22 * 添加用户
23 * @param user
24 */
25 void insertUser(User user);
26
27 }
③加载UserMpper.xml

④建立测试类
1 public class UserMapperTest {
2
3 @Test
4 public void getUserById() {
5 SqlSessionFactory sqlSessionFactory =
6 SqlSessionFactoryUtils.getSqlSessionFactory();
7 SqlSession sqlSession = sqlSessionFactory.openSession();
8 UserMapper mapper = sqlSession.getMapper(UserMapper.class);
9 User user = mapper.getUserById(31);
10 System.out.println(user);//User{id=31, username='杨玉环', sex='0', birthday=Sat Apr 07 00:00:00 CST 2018, address='李隆基', uuid='null'}
11 sqlSession.close();
12 }
13
14 @Test
15 public void getUserByName() {
16 SqlSessionFactory sqlSessionFactory =
17 SqlSessionFactoryUtils.getSqlSessionFactory();
18 SqlSession sqlSession = sqlSessionFactory.openSession();
19 UserMapper mapper = sqlSession.getMapper(UserMapper.class);
20 List<User> users = mapper.getUserByName("张");
21 for (User user : users) {
22 System.out.println(user);
23 }
24 /*User{id=10, username='张三', sex='1', birthday=Thu Jul 10 00:00:00 CST 2014, address='北京市', uuid='null'}
25 User{id=16, username='张小明', sex='1', birthday=null, address='河南郑州', uuid='null'}
26 User{id=24, username='张三丰', sex='1', birthday=null, address='河南郑州', uuid='null'}*/
27 sqlSession.close();
28 }
29
30 @Test
31 public void insertUser() {
32 SqlSessionFactory sqlSessionFactory =
33 SqlSessionFactoryUtils.getSqlSessionFactory();
34 SqlSession sqlSession = sqlSessionFactory.openSession();
35 UserMapper mapper = sqlSession.getMapper(UserMapper.class);
36 User user = new User();
37 user.setUsername("lisi");
38 user.setSex("1");
39 user.setBirthday(new Date());
40 user.setAddress("北京");
41 mapper.insertUser(user);
42 sqlSession.commit();
43 sqlSession.close();
44 }
45 }
五、SqlMapConfig.xml配置

1、properties
①属于核心文件配置
1 <!-- 加载规则,首先加载标签内部属性,再加载外部文件,名称相同时,会替换相同名称的内容 --> 2 <properties resource="jdbc.properties"> 3 <property name="jdbc.username" value="root1"/> 4 <property name="jdbc.password" value="root"/> 5 </properties>
②jdbc.properties
1 jdbc.driver=com.mysql.jdbc.Driver 2 jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8 3 jdbc.username=root 4 jdbc.password=root
2、typeAliases
自定义别名
1 <typeAliases> 2 <!-- 单个别名定义 --> 3 <!-- <typeAlias type="com.itheima.mybatis.pojo.User" alias="user"/> --> 4 <!-- 别名包扫描器(推荐使用此方式),整个包下的类都被定义别名,别名为类名,不区分大小写--> 5 <package name="com.itheima.mybatis.pojo"/> 6 </typeAliases>
3、mapper
1 <mappers> 2 <!-- 第一种方式,加载 resource--> 3 <mapper resource="mapper/user.xml"/> 4 <!-- <mapper resource="mapper/UserMapper.xml"/> --> 5 6 <!-- 第二种方式,class扫描器要求: 7 1、映射文件与接口同一目录下 8 2、映射文件名必需与接口文件名称一致 9 --> 10 <!-- <mapper class="com.itheima.mybatis.mapper.UserMapper"/> --> 11 12 <!-- 第三种方式,包扫描器要求(推荐使用此方式): 13 1、映射文件与接口同一目录下 14 2、映射文件名必需与接口文件名称一致 15 --> 16 <package name="com.itheima.mybatis.mapper"/> 17 </mappers>
六、小结
1、#{} 和${}
#{} 表示一个占位符号,通过#{} 可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{} 可以有效防止sql注入。#{}可以接受简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其他名称。
${}表示拼接sql串,通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接受简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
2、parameterType和resultype
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中。

浙公网安备 33010602011771号