关于myBatis以前一点都没有了解,但是好多招聘上面都是要求mybatis.现在开始基础学习下:
MyBatis的前身叫iBatis,本是apache的一个开源项目, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录。
1)MyBATIS 目前提供了三种语言实现的版本,包括:Java、.NET以及Ruby。(我主要学习java,就讲java的使用)
2)它提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。
3)mybatis与hibernate的对比?
mybatis提供一种“半自动化”的ORM实现。
这里的“半自动化”,是相对Hibernate等提供了全面的数据库封装机制的“全自动化”ORM实现而言,“全自动”ORM实现了POJO和数据库表之间的映射,以及 SQL 的自动生成和执行。
而mybatis的着力点,则在于POJO与SQL之间的映射关系。
一:mybatis的project
我们先建立一个Mybatis的project,项目具体如下:
首先要导入两个包:一个是mybatis的jar包,一个是mysql的驱动包
mybatis需要jar包:mybatis-3.3.0.jar
mysql驱动jar包:mysql-connector-java-5.1.15.-bin.jar
同样的我们要创建数据库:
这个是我们整体的项目工程:
二:XML配置
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
1:添加mybatis配置文件mybatis.cfg.xml
Mybatis的全局配置文件,主要用于配置Mybatis的运行环境(事务管理器、数据源等)。具体详情可见Mybatis说明文档。
下面通过一个简单的示例,来简要说明这个配置文件。
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
3 <configuration>
4 <environments default="development">
5 <environment id="development">
6 <transactionManager type="JDBC">
7 </transactionManager>
8 <!-- 数据库连接配置信息 -->
9 <dataSource type="POOLED">
10 <property name="driver" value="com.mysql.jdbc.Driver"/>
11 <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
12 <property name="username" value="root"/>
13 <property name="password" value="root"/>
14 </dataSource>
15 </environment>
16 </environments>
17
18 <!-- 注册userMapper.xml文件 -->
19 <mappers>
20 <mapper resource = "mapper/userMapper.xml"/>
21 </mappers>
22 </configuration>
头文件(1~2行):第1行是xml声明,声明该xml文件的字符集为UTF-8;第2行是DTD文件类型声明(外部DTD),用于约束该xml文件的结构。引用的DTD约束的格式为<!DOCTYPE 根元素 SYSTEM "DTD文件路径">(本地文件),或<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文件URL">(公共文件),这里是约束configuaration元素的结构为链接中的DTD文件所约束的那样
environments元素(4~16行):用于配置要创建的SqlSessionFactory实例的环境。每个数据库对应一个SqlSessionFactory实例,每个SqlSessionFactory实例只能选择一种环境(environments元素中可以定义多个environment元素)。
- 第4行:默认的环境id。
- 第5行:定义一个environment元素,并设定环境id。
- 第6行:事务管理器的配置,可选"JDBC"或"MANAGED"。【注:Spring+Mybatis不需要配置事务管理器,因为Spring会用自带管理器覆盖这些配置】
- "JDBC":直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
- "MANAGED":不提交或回滚一个连接,而是让容器来管理事务的整个生命周期,默认情况下它会关闭连接
- 第9~14行:数据源的配置。第12行是配置数据源类型,内置了"UNPOOLED","POOLED"和"JNDI";第13~18行是设定数据源。
- "UNPOOLED":不使用数据库连接池。只有driver,url,username,password,defaultTransactionIsolationLevel五个属性,其中最后一个属性是指默认的连接事务隔离级别。
- "POOLED":使用数据库连接池。除了"UNPOOLED"中的5个属性之外,还多了一些连接池属性,比如poolMaximumActiveConnections(最大活动连接数)、poolMaximumIdleConnections(最大空闲连接数)等(详见说明文档)。
- "JNDI":为了能在如EJB或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用。只需"initial_context"和"data_source"两个属性。
- 另外,也可以将type设置为一个数据源类,使用任何第三方数据源。
mappers元素(19~21行):用于设定映射文件路径。可以通过classpath相对路径、文件系统绝对路径设定映射文件,还可以通过类名、包名设定映射接口
2.userMapper.xml
sql映射文件,主要用于实现数据库操作的具体细节。此文件需要在MybatisConfig.xml中加载。
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3
4 <!-- 为这个mapper指定一个唯一的namespace,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证包名是惟一的 -->
5 <mapper namespace="mapper.userMapper">
6
7 <!-- 在select标签中编写查询的sql语句,设置select标签的id属性为getUser,id属性值必须是唯一的,不能够重复使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果类型。
8 -->
9 <!-- 对于查询单条记录,必须保证查询出来的记录只有一个,如果有多个mybatis是会报错的,而不是就取多条记录中的第一个。 -->
10 <select id="getUser" parameterType="String" resultType="beans.User">
11 select * from users where username=#{id}
12 </select>
13
14 <insert id="insertUser" parameterType="beans.User">
15 insert into users(username, password) value(#{username},#{password})
16 </insert>
17
18 <update id="update" parameterType="beans.User">
19 update users set username=#{username}, password=#{password} where id=#{id}
20 </update>
21
22 <delete id="delete" parameterType="int">
23 delete from users where id=#{id}
24 </delete>
25
26 <!--id为该条SQL的名称,在该Mapper下不能重复
27 resultType里填写集合泛型,不论返回值是List还是单个类型,都填写泛型或者单个类型即可,
28 mybatis会自动猜测返回值是一个类型还是集合-->
29 <select id="selectAllUsers" resultType="beans.User">
30 select * from users
31 </select>
32
33 </mapper>
- 头文件(1~2行):同上,这里是约束mapper元素的结构为链接中的DTD文件所约束的那样。
- 命名空间(5行):最基本的意义,是给这个mapper命名用于区分;更为高级的用法,则是接口绑定(面向接口编程)。namespace的命名方式分为两种:完全限定名和短名称。本例中使用的就是完全限定名。使用短名称时,必须确保这个短名称在系统中是唯一的,否则只能使用完全限定名。
- 接口绑定:将namespace设为DAO接口,将接口中的方法都通过mapper中的元素实现(元素id与接口方法一一对应),就可以不用写DAO实现类,Mybatis会通过绑定自动找到要执行的sql语句。
mapper顶级元素(4~61行):mapper中有8个顶级元素,分别是insert,delete,update,select(映射增删改查语句),sql(重用sql语句块),resultMap(描述如何从结果集中加载对象),cache(缓存配置),cache-ref(其他namespace缓存配置)。
insert、delete、update(5~23行):基本格式就是<元素名 元素属性>sql语句</元素名>。其中,元素名即为insert/delete/update中的一个,可设定的元素属性有9个,这里只列出5个,一般设定1,2即可。在sql语句中,用#{}表示占位符,执行时将#{}替换为?,然后将括号内的参数传递给?。
- id:元素标识。
- parameterType:接受的参数类型,可为完全限定名或别名。默认为unset。传入多个参数时,这个属性应忽略,在#{}中直接以各参数名表示。(如:18~23行)
- .......
下面看Java的操作:
数据库操作在代码中的实现步骤大体如下:
- 创建IO流,通过Resources类中的getResourceAsStream方法载入全局配置文件(mybatis.cfg.xml)。
- 由SqlSessionFactoryBuilder对象的build方法,创建SqlSessionFactory对象。
- 由SqlSessionFactory对象的openSession方法,创建SqlSession对象。
- 由SqlSession对象,操作数据库。
- 关闭SqlSession对象,然后关闭IO流.
下面主要讲解一下通过SqlSession对象操作数据库的内容。
1.SqlSession类中的常用方法
目前主要用到过的方法有:
- insert,delete,update:对数据库进行增/删/改操作。注意:进行了这些操作之后,必须调用commit()提交事务,否则数据库记录不会改变。
返回值:int,操作所影响的行数。
参数:("sqlID",param):
- sqlID:StudentMapper.xml中对应的sql元素的id,若有多个mapper,可以通过mapper.sqlID的形式指定。
- param:若对应的接口函数只需要传入一个参数,直接将这个参数传入即可。【最好用变量的形式传入。直接传常量可能会导致类型转换异常】
若需传入多个参数,则应该用HashMap<String,Object>传入参数。其中,String是mapper.xml中的参数名(#{xx}),Object是参数值。将多个参数放入map后,将map作为参数传入即可。
- commit():刷新批处理语句并提交数据库连接。在增删改之后必须调用。
- selectOne("sqlID",param):参数意义同上。返回值:mapper.xml中规定的返回值类型。
- selectList("sqlID",param):同上。返回值:List<E>,其中E为mapper.xml中规定的返回值类型。
- close():关闭会话,释放资源。
- POJO类中的构造方法的参数类型,如果是基本数据类型,应该写成其包装类的形式(比如int写为Integer)。因为mapper.xml中的javaType会自动转为完全限定名(比如int转为java.lang.Integer)。如果在resultMap中定义了constructor元素,映射到POJO类时会是完全限定名的类型,如果构造方法中的参数类型不是包装类,就会报错(找不到参数类型为xxx的构造函数)。
- 务必在insert/delete/update之后执行commit!否则一切操作都不会在数据库中生效!
下面看一下Java类文件:
POJO类:
1 package beans;
2
3 public class User {
4
5 private int id;
6
7 private String username;
8 private String password;
9
10
11 /**
12 * @return the id
13 */
14 public int getId() {
15 return id;
16 }
17 /**
18 * @param id the id to set
19 */
20 public void setId(int id) {
21 this.id = id;
22 }
23 /**
24 * @return the username
25 */
26 public String getUsername() {
27 return username;
28 }
29 /**
30 * @param username the username to set
31 */
32 public void setUsername(String username) {
33 this.username = username;
34 }
35 /**
36 * @return the password
37 */
38 public String getPassword() {
39 return password;
40 }
41 /**
42 * @param password the password to set
43 */
44 public void setPassword(String password) {
45 this.password = password;
46 }
47
48 /* (non-Javadoc)
49 * @see java.lang.Object#toString()
50 */
51 @Override
52 public String toString() {
53 return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
54 }
55
56 }
MybatisUtil工具类:
1 package utils;
2
3 import java.io.IOException;
4 import java.io.Reader;
5
6 import org.apache.ibatis.io.Resources;
7 import org.apache.ibatis.session.SqlSession;
8 import org.apache.ibatis.session.SqlSessionFactory;
9 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
10
11 public class MybatisUtil {
12
13 private static SqlSessionFactory sqlSessionFactory = null;
14
15 static{
16 try {
17 Reader read = Resources.getResourceAsReader("mybatis.cfg.xml");
18 sqlSessionFactory = new SqlSessionFactoryBuilder().build(read);
19 } catch (IOException e) {
20 e.printStackTrace();
21 }
22 }
23
24 public static SqlSession getSession(){
25 return sqlSessionFactory.openSession(true);
26 }
27 }
测试类:
1 package test;
2
3 import java.io.IOException;
4
5 import org.apache.ibatis.session.SqlSession;
6
7 import beans.User;
8 import utils.MybatisUtil;
9
10 public class Test {
11
12 public static void main(String[] args) throws IOException {
13
14 //mybatis的配置文件
15 //String resource = "mybatis.cfg.xml";
16
17 //使用类加载器加载mybatis配置文件,它也加载关联的映射文件
18 //InputStream is = Test.class.getClassLoader().getResourceAsStream(resource);
19
20 //构建sqlSession的工厂
21 //SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
22
23 //使用mybatis提供的Resource类加载mybatis的配置文件(它也加载关联的映射文件)
24 //Reader read = Resources.getResourceAsReader(resource);
25
26 //构建sqlSession工厂
27 //SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(read);
28 //创建能执行映射文件中的sql的sqlSession
29 //SqlSession sqlSession = sqlSessionFactory.openSession();
30 SqlSession sqlSession = MybatisUtil.getSession();
31
32 //映射sql的标识字符串,mapper.userMapper是userMapper.xml文件中mapper标签的namespace属性值
33 //getUser是select标签的id属性值,通过select标签的id属性值就可以找到要执行的sql
34 String statament = "mapper.userMapper.getUser"; //映射sql的标识字符串
35 //执行查询返回一个唯一的user对象的sql
36 User user = sqlSession.selectOne(statament, "zxl");
37
38 System.out.println(user);
39 }
40
41 }
看上面的例子可以看出,获取SqlSessionFactory一共有两种方式:
通过myBatis提供的Resources.getResourceAsReader(resource), 然后通过New SqlSessionFactoryBuilder().build()来创建SqlSessionFactory.
通过使用类加载器加载mybatis配置文件,它也加载关联的映射文件,Test.class.getClassLoader().getResourceAsStream(resource);
上面的查询结果:根据“mapper.userMapper.getUser”找到sql语句:“select * from users where username=#{id}”, 然后将参数传递进去。
一个复杂些的CRUD:
1 package test;
2
3 import java.util.HashMap;
4 import java.util.List;
5
6 import org.apache.ibatis.session.SqlSession;
7
8 import beans.User;
9 import utils.MybatisUtil;
10
11 public class TestCRUD {
12
13 public static void main(String[] args) {
14
15 //查找一个用户
16 SqlSession sqlSession = MybatisUtil.getSession();
17 String statament = "mapper.userMapper.getUserbyMore";
18
19 HashMap<String, Object> paras = new HashMap<String, Object>();
20 paras.put("username", "zxl");
21 paras.put("password", "12345");
22
23 User user = new User();
24 user = sqlSession.selectOne(statament, paras); //通过多个参数去查找,传入参数应该是HashMap,key是数据表中列参数
25 System.out.println("查询结果:"+ user);
26
27 //更新用户
28 statament = "mapper.userMapper.update";
29 User userupdate = new User();
30 userupdate.setId(2);
31 userupdate.setUsername("zxllll");
32 userupdate.setPassword("345");
33 int result = sqlSession.update(statament, userupdate);
34 System.out.println("update result: " + result);
35
36 //添加一个用户,前面有删去用户,添加的主键会不连续。
37 statament = "mapper.userMapper.insertUser";
38 User useradd = new User();
39 useradd.setUsername("zxl333");
40 useradd.setPassword("333");
41 result = sqlSession.insert(statament, useradd);
42 System.out.println("insert new user result: " + result);
43
44 //删去一个用户
45 statament = "mapper.userMapper.delete";
46 result = sqlSession.delete(statament, 2);
47 System.out.println("delete user result: " + result);
48
49 //查找所有用户
50 statament = "mapper.userMapper.selectAllUsers";
51 List<User> list = sqlSession.selectList(statament);
52 System.out.println("select all user result: " + list);
53 sqlSession.close();
54 }
55 }
上面查找是通过username和password来查找的,所以在userMapper.xml中添加一部分如下:
1 <select id="getUserbyMore" resultType="beans.User">
2 select * from users where username=#{username} and password=#{password}
3 </select>
如输入是多个参数,则parameterType应该是空的。并且Sql语句中where里面条件判断必须是数据表字段。