##面向对象的世界与关系数据库的鸿沟 Java语言是一门面向对象的程序设计语言,面向对象是从软件工程的基本原则高内聚低耦合等理论基础上发展起来的。java
正式编程语言与数据库的不匹配,咱们没有办法在Java程序中像操做对象同样的方式去操做关系型数据库当中的数据。才须要一个中间的映射技术,帮助咱们自动的实现对象与二元表之间的转换。这种对象关系数据库映射技术应运而生。mysql
##ORMgit
#MyBatis MyBatis官方网址github
在2010年这个项目由Apache基金会迁移到了Google Code并更名为MyBatis。目前MyBatis在企业开发中应用很是普遍。本质上是ORM框架,可是与传统ORM框架显著不一样的是,并不是创建Java对象到关系型数据库表数据之间的映射关系。而是创建,对对象的操做方法到SQL语句之间的映射关系。因为SQL语句自己是须要由SQL语句来编写的。因此MyBatis的优点是可让开发者使用关系型数据库的全部的特性。好比存储过程、视图、复杂查询等等。同时因为MyBatis也让开发者对执行的SQL得到了更多的控制,因此开发者能够编写更加高效率的SQL语句,来提升应用程序对数据库的访问效率。MyBatis是经过XML文件定义后端数据库的,配置Java方法与后端映射关系的。sql
##MyBatis功能架构 MyBatis功能架构有三层, ###接口层 第一层是接口层,提供给外部使用的API接口。提供给咱们程序开发人员,开发人员使用本地API来操做数据库,接口层接到调用请求后,将会把请求转发给数据处理层进行执行。 ###数据库处理层 第二层是数据处理层,主要负责具体SQL的查找、SQL解析、SQL执行和执行结果结果的映射处理。主要目的是根据调用请求来完成一次数据库操做 ###基础支持层 最后一层是基础支撑层,主要负责最基础的数据支持,数据库的链接管理、事务管理、配置加载、缓存处理。都是共用的功能,把这些功能抽象出来做为最基础的组件。给上层的数据库处理层提供最基础的支撑。 数据库
##MyBatis工做流机制 首先咱们须要在应用程序启动的时候,加载XML文件。该XML文件定义了后端数据库的地址,同时也定义了SQL与Java方法之间的映射关系apache
##MyBatis环境搭建 MyBatis下载最终版本编程
首先咱们须要下载MyBatis,解压缩后查看目录树以下后端
mybatis/ └── mybatis-3.4.1 ├── LICENSE ├── NOTICE ├── lib │ ├── ant-1.9.6.jar │ ├── ant-launcher-1.9.6.jar │ ├── asm-5.0.4.jar │ ├── cglib-3.2.2.jar │ ├── commons-logging-1.2.jar │ ├── javassist-3.20.0-GA.jar │ ├── log4j-1.2.17.jar │ ├── log4j-api-2.3.jar │ ├── log4j-core-2.3.jar │ ├── ognl-3.1.8.jar │ ├── slf4j-api-1.7.21.jar │ └── slf4j-log4j12-1.7.21.jar ├── mybatis-3.4.1.jar └── mybatis-3.4.1.pdf 2 directories, 16 files
应用程序使用MyBatis须要把解压缩当中的mybatis-3.x.x.jar放置到lib目录下,更加推荐Maven方式,因为MyBatis一样基础JDBC来访问后端数据库的,因此咱们一样须要对应数据库的JDBC驱动。api
###Maven
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency>
###Gradle
// https://mvnrepository.com/artifact/org.mybatis/mybatis compile group: 'org.mybatis', name: 'mybatis', version: '3.4.1'
##SqlSessionFactory 每一个MyBatis应用都是基于SqlSessionFactory实例为中心的。经过SqlSessionFactory实例能够获取,将对象操做转换成数据库SQL的Session。咱们经过XML配置文件,能够完成SqlSessionFactory的配置。首先咱们要来完成配置文件,整个XML配置文件包含了对MyBatis系统的核心配置。包括后端的数据库链接实例数据源,和决定事务范围事务处理的事务管理器。
###transactionManager 在transactionManager有type属性,提供了两个选项,jdbc和managed。
###dataSource 以后咱们要配置后端的数据库源,与JDBC一致,主要包括4个属性。分别是数据库驱动、URL、用户名、密码。 ###官方文档SqlSessionFactory的配置
<environments default="development"> <environment id="development"> <!-- 事务管理 --> <transactionManager type="JDBC"> <property name="..." value="..."/> </transactionManager> <!-- 数据库链接数据源 --> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>
##Java对象 ###构造对象 在配置完毕MyBatis后,咱们就须要对程序进行编写,因为MyBatis是Object Relation Mapping。咱们要定义Java对象,而后创建对象和对象操做SQL语句之间的映射关系。咱们定义的Java对象包括一些属性。咱们这里以User对象做为示例。
package com.hava.mybatis.user.entity; /** * Created by zhanpeng on 09/10/2016. */ public class User { private Integer id; private String userName; private String corp; //公司 public User(Integer id,String userName,String corp) { this.id = id; this.userName = userName; this.corp = corp; } //Getter and Setter public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getCorp() { return corp; } public void setCorp(String corp) { this.corp = corp; } }
###构建接口 有了Java对象之后,咱们还须要定义对这个Java对象的操做。MyBatis与其余与其余传统ORM框架是不一样的。不是直接创建对象和关系型数据库表数据的映射,而是采起更加灵活的方式,将对对象的操做与关系型数据库的SQL语句创建关系。因此咱们须要定义一些对对象的操做。
咱们使用Java里面的Interface接口的方式,来定义对对象的操做。
package com.hava.mybatis.user.entity; /** * Created by zhanpeng on 09/10/2016. */ public interface GetUserInfo { public User getUser(Integer id); public void addUser(User user); public void updateUser(User user); public void deleteUser(User user); }
##建立Java对象和SQL语句映射关系配置文件 Java对象接口与SQL语句的映射关系,映射关系也是经过配置文件来完成的。配置也是XML文件,配置文件中最重要的是包含Mapper的标签。 ###namespace 标签的namespace属性的值是指向Java对象接口操做类的位置。 ###定义SQL语句 获取数据库中的信息,检索数据库获取User信息,而后映射到Java的User对象中。因此咱们这里的select id定义为getUser,对应接口的具体方法。而后parameterType定义int,因为咱们的方法参数为int,resultType指向咱们定义的Java的User类。但愿MyBatis把返回的结果自动转化成定义为Java对象。注意加完整路径。
<?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.hava.mybatis.user.entity. GetUserInfo"> <!-- 定义SQL语句 --> <select id="getUser" parameterType="int" resultType="com.hava.mybatis.user.entity.User"> select id, userName,corp from user where id = #{id} </select> </mapper>
##注册配置文件 咱们还须要将这个映射文件,加载到注册到刚开始配置的SqlSessionFactory的配置文件中,咱们要在以前的配置文件中增长mappers的标签。
##完成数据库查询 MyBatis完成数据库查询须要完成三个步骤,首先须要加载配置文件,而后建立一个SqlSessionFactory的实例。第二步经过SqlSessionFactory获取sqlSession对象,sqlSession可以帮助咱们执行具体的SQL操做。最后一步就是利用Session进行查询。
##MyBatis查询实例 ###数据库初始化
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(100) NOT NULL, `corp` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
手动添加了数据 ###修改pom.xml以支持xml运行
<!-- 因为该项目须要添加在src下的xml文件进行运行则增长如下配置 --> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build>
###mybatis-conf.xml 上面的例子并无添加mybatis的DOCTYPE定义
<?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"> <!--<property name="..." value="..."/>--> </transactionManager> <!-- 数据库链接数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.1.200/test"/> <property name="username" value="root"/> <property name="password" value=""/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/hava/mybatis/user/entity/userMapper.xml" /> </mappers> </configuration>
###执行查询过程
package com.hava.mybatis.user.service; import com.hava.mybatis.user.entity.GetUserInfo; import com.hava.mybatis.user.entity.User; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; /** * Created by zhanpeng on 09/10/2016. */ public class HelloMyBatis { public static void main(String [] args) { //1.声明MyBatis的配置文件目录 String resource = "mybatis-conf.xml"; //2.加载应用程序配置文件 InputStream inputStream = HelloMyBatis.class.getClassLoader().getResourceAsStream(resource); //3.建立SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); Configuration configuration = sqlSessionFactory.getConfiguration(); //Exception in thread "main" org.apache.ibatis.binding.BindingException: Type interface com.hava.mybatis.user.entity.GetUserInfo is already known to the MapperRegistry. // configuration.addMapper(GetUserInfo.class); //4.获取Session SqlSession sqlSession = sqlSessionFactory.openSession(); try { //5.获取操做类 GetUserInfo getUserInfo = sqlSession.getMapper(GetUserInfo.class); //6.完成查询操做 User user = getUserInfo.getUser(1); System.out.println("[user.getUserName]:" + user.getUserName()); } finally { //7.关闭session sqlSession.close(); } } }
###注意 在执行演示语句发生异常
Exception in thread "main" org.apache.ibatis.binding.BindingException: Type interface com.hava.mybatis.user.entity.GetUserInfo is already known to the MapperRegistry. // configuration.addMapper(GetUserInfo.class);
说明若是在配置文件当中,已经mapper了接口文件,则不须要在代码中再次mapper。 ###执行结果
[user.getUserName]:ZhangSan Process finished with exit code 0
#MyBatis优点与劣势
#经过注解的方式
package com.hava.mybatis.user.repository; import com.hava.mybatis.user.entity.User; import org.apache.ibatis.annotations.Select; /** * Created by zhanpeng on 09/10/2016. */ public interface GetUserInfoAnnotation { @Select("select * from user where id = #{id}") public User getUser(int id); }
变动主程序
//1.声明MyBatis的配置文件目录 String resource = "mybatis-conf.xml"; //2.加载应用程序配置文件 InputStream inputStream = HelloMyBatis.class.getClassLoader().getResourceAsStream(resource); //3.建立SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); Configuration configuration = sqlSessionFactory.getConfiguration(); //Exception in thread "main" org.apache.ibatis.binding.BindingException: Type interface com.hava.mybatis.user.entity.GetUserInfo is already known to the MapperRegistry. configuration.addMapper(GetUserInfoAnnotation.class); //4.获取Session SqlSession sqlSession = sqlSessionFactory.openSession(); try { //5.获取操做类 // GetUserInfo getUserInfo = sqlSession.getMapper(GetUserInfo.class); //使用注解的方式 GetUserInfoAnnotation getUserInfo = sqlSession.getMapper(GetUserInfoAnnotation.class); //6.完成查询操做 User user = getUserInfo.getUser(1); System.out.println("[user.getUserName]:" + user.getUserName()); } finally { //7.关闭session sqlSession.close(); }
##其余数据库操做
咱们在openSession添加了true,是因为jdbc默认是以事务进行提交。可是在MyBatis是不一致的,默认会开启事务。若是不设置true,都是以事务的形式提交。
###定义正删改查接口
package com.hava.mybatis.user.repository; import com.hava.mybatis.user.entity.User; /** * Created by zhanpeng on 09/10/2016. */ public interface UserOp { public void addUser(User user); public void updateUser(User user); public void deleteUser(int id); public User getUser(int id); }
###添加定义文件 insert经过useGeneratedKeys获取自增id号
<?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.hava.mybatis.user.repository.UserOp"> <insert id="addUser" parameterType="com.hava.mybatis.user.entity.User" useGeneratedKeys="true" keyProperty="id"> insert into user (userName,corp) value(#{userName},#{corp}) </insert> <!-- 定义SQL语句 --> <select id="getUser" parameterType="int" resultType="com.hava.mybatis.user.entity.User"> select id, userName,corp from user where id = #{id} </select> <update id="updateUser" parameterType="com.micro.profession.mybatis.User"> update user set userName = #{userName} , corp = #{corp} where id = #{id} </update> <delete id="deleteUser" parameterType="com.micro.profession.mybatis.User"> delete from user where id = #{id} </delete> </mapper>
###修改Entity定义
public User(Integer id,String userName,String corp) public User(String userName,String corp)
必须均存在,用于MyBatis扫描和设置对象的属性,得知MyBatis并非经过getter setter对对象的值进行设置。
package com.hava.mybatis.user.entity; /** * Created by zhanpeng on 09/10/2016. */ public class User { private Integer id; private String userName; private String corp; public User(Integer id,String userName,String corp) { this.id = id; this.userName = userName; this.corp = corp; } public User(String userName,String corp) { this.userName = userName; this.corp = corp; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getCorp() { return corp; } public void setCorp(String corp) { this.corp = corp; } }
###执行函数
package com.hava.mybatis.user.service; import com.hava.mybatis.user.entity.User; import com.hava.mybatis.user.repository.GetUserInfoAnnotation; import com.hava.mybatis.user.repository.UserOp; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; /** * Created by zhanpeng on 09/10/2016. */ public class HelloMyBatisMoreOp { public static void main(String[] args) { moreOp(); } public static void moreOp() { // 1. 声明配置⽂件 String resource = "mybatis-conf.xml"; // 2. 加载应⽤配置⽂件 InputStream is = HelloMyBatisMoreOp.class.getClassLoader() .getResourceAsStream(resource); // 3. 建立SqlSessonFactory SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder() .build(is); SqlSession session = sessionFactory.openSession(true); try { // 5. 获取操做类 UserOp userOp = session.getMapper(UserOp.class); User user = new User("XiaoMing", "Netease"); // 插⼊⽤户 userOp.addUser(user); System.out.println(user.getId()); // 查询⽤户 user = userOp.getUser(user.getId()); System.out.println("userId:" + user.getId() + ", userName:" + user.getUserName() + ", corp:" + user.getCorp()); user.setUserName("LiMing"); // 更新⽤户 userOp.updateUser(user); // 删除⽤户 userOp.deleteUser(user.getId()); } finally { // 7.关闭Session session.close(); } } }
###执行结果
4 userId:4, userName:XiaoMing, corp:Netease Process finished with exit code 0
###MyBatis的事务 若是openSession(true)则会自动提交sql,不会发生事务处理。若是采用默认方式openSession()
,则会开启事务,进行处理,若是开启事务,则须要手动进行提交工做。session.commit()
123