前言
一直在使用,从未系统的总结起来。所以这里给大家带来的是mybatis的总结,系统大家能够对这个框架有一定的系统的学习与认识。
mybatis和Hibernate应该是现在主流的ORM框架了。 mybatis学习的步骤: mybatis入门 --> 全局配置文件和映射文件详解 --> 高级映射(一对一,一对多,多对多) -->延迟加载机制 -->一级缓存, 二级缓存(整合ehcache) --> spring整合mybatis --> 逆向工程一、Mybatis简介
- Mybatis是Apache的一个Java开源项目,是一个支持动态Sql语句的持久层框架。Mybatis可以将Sql语句配置在XML文件中,避免 将Sql语句硬编码在Java类中。
- MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置 以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。
总结一下:
- 1)支持普通sql查询
- 2)高级映射
- 3)存储过程
- 4)消除了几乎所有jdbc代码和参数的手工设置以及结果集的检索
二、Mybatis与JDBC、Hibernate的区别
2.1 Mybatis与JDBC的区别
- Mybatis通过参数映射方式,可以将参数灵活的配置在SQL语句中的配置文件中,避免在Java类中配置参数(JDBC)
- Mybatis通过输出映射机制,将结果集的检索自动映射成相应的Java对象,避免对结果集手工检索(JDBC)
- Mybatis可以通过Xml配置文件对数据库连接进行管理。
三、感受JDBC和Mybatis
MyBatis 是来和数据库打交道。那么在这之前,我们是使用 JDBC 来对数据库进行增删改查等一系列操作的,而我们之所以会放弃
使用 JDBC,转而使用 MyBatis 框架,这是为什么呢? 为什么使用Mybatis比JDBC直接连接方便和性能上好很多呢?- 新建Person实体类
public class Person { private Long pid; private String pname; public Long getPid() { return pid; } public void setPid(Long pid) { this.pid = pid; } public String getPname() { return pname; } public void setPname(String pname) { this.pname = pname; }}
- JDBC 查询操作
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.List; import javax.swing.DebugGraphics; import com.ys.bean.Person; public class CRUDDao { //MySQL数据库驱动 public static String driverClass = "com.mysql.jdbc.Driver"; //MySQL用户名 public static String userName = "root"; //MySQL密码 public static String passWord = "654321"; //MySQL URL public static String url = "jdbc:mysql://localhost:3306/study"; //定义数据库连接 public static Connection conn = null; //定义声明数据库语句,使用 预编译声明 PreparedStatement提高数据库执行性能 public static PreparedStatement ps = null; //定义返回结果集 public static ResultSet rs = null; /** * 查询 person 表信息 * @return:返回 person 的 list 集合 */ public static ListreadPerson(){ List list = new ArrayList<>(); try { //加载数据库驱动 Class.forName(driverClass); //获取数据库连接 conn = DriverManager.getConnection(url, userName, passWord); //定义 sql 语句,?表示占位符 String sql = "select * from person where pname=?"; //获取预编译处理的statement ps = conn.prepareStatement(sql); //设置sql语句中的参数,第一个为sql语句中的参数的?(从1开始),第二个为设置的参数值 ps.setString(1, "qzy"); //向数据库发出 sql 语句查询,并返回结果集 rs = ps.executeQuery(); while (rs.next()) { Person p = new Person(); p.setPid(rs.getLong(1)); p.setPname(rs.getString(2)); list.add(p); } } catch (Exception e) { e.printStackTrace(); }finally{ //关闭数据库连接 if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(ps!=null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; } public static void main(String[] args) { System.out.println(CRUDDao.readPerson()); }}
- 分析问题 1)问题一:数据库连接,使用时就创建,使用完毕就关闭,这样会对数据库进行频繁的获取连接和关闭连接,造成数据库资源浪费, 影响数据库性能。 设想解决:使用数据库连接池管理数据库连接 2)问题二:将 sql 语句硬编码到程序中,如果sql语句修改了,那么需要重新编译 Java 代码,不利于系统维护 设想解决:将 sql 语句配置到 xml 文件中,即使 sql 语句变化了,我们也不需要对 Java 代码进行修改,重新编译 3)问题三:在 PreparedStatement 中设置参数,对占位符设置值都是硬编码在Java代码中,不利于系统维护 设想解决:将 sql 语句以及占位符和参数都配置到 xml 文件中 4)问题四:从 resultset 中遍历结果集时,对表的字段存在硬编码,不利于系统维护 设想解决:将查询的结果集自动映射为 Java 对象 5)问题五:重复性代码特别多,频繁的 try-catch 设想解决:将其整合到一个 try-catch 代码块中 6)问题六:缓存做的很差,如果存在数据量很大的情况下,这种方式性能特别低 设想解决:集成缓存框架去操作数据库 7)问题七:sql 的移植性不好,如果换个数据库,那么sql 语句可能要重写 设想解决:在 JDBC 和 数据库之间插入第三方框架,用第三方去生成 sql 语句,屏蔽数据库的差异
四、基于XML的Mybatis入门实例
4.1 创建数据库表
创建完成,随便写几条数据进去。4.2 创建一个Java项目,并导入相应的jar包
备注:log4j和Junit不是必须的,但是我们为了查看日志以及便于测试,加入了这两个jar包
目录结构:4.3 项目中添加数据库配置文件 mybatis-configuration.xml
4.4 定义表对应的实体类
package com.lance.mybatis.bean;import java.util.Date;public class User { private int id; private String username; private int password; private String sex; private Date birthday; private String address; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getPassword() { return password; } public void setPassword(int password) { this.password = password; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password=" + password + ", sex='" + sex + '\'' + ", birthday=" + birthday + ", address='" + address + '\'' + '}'; }}
4.5 定义操作 user 表的sql映射文件userMapper.xml
select LAST_INSERT_ID() insert into user(username,password,sex,birthday,address) value(#{username},#{password},#{sex},#{birthday},#{address})update user set username=#{username} where id=#{id} delete from user where id=#{id}
4.6 向 mybatis-configuration.xml 配置文件中注册 userMapper.xml 文件
4.7 测试功能类
package com.lance.mybatis.test;import com.lance.mybatis.bean.User;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.Before;import org.junit.Test;import java.io.InputStream;import java.util.Date;import java.util.List;/** * @author lance(ZYH) * @function * @date 2018-07-07 21:10 */public class MybatisTest { SqlSession session = null; @Before public void init() { //定义mybatis全局配置文件 String resource = "com/lance/mybatis/config/mybatis-configuration.xml"; //加载 mybatis 全局配置文件 InputStream inputStream = MybatisTest.class.getClassLoader() .getResourceAsStream(resource); //构建sqlSession的工厂 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //根据 sqlSessionFactory 产生 session session = sessionFactory.openSession(); } //根据id查询user表数据 @Test public void getUserById() { /*这个字符串由 userMapper.xml 文件中 两个部分构成的 namespace 的值
五、总结
5.1 插入数据之后的主键值
1)数据库设置主键自增机制
userMapper.xml 文件中定义:select LAST_INSERT_ID() insert into user(username,password,sex,birthday,address) value(#{username},#{password},#{sex},#{birthday},#{address})
2)非自增主键机制
select UUID() insert into user(id,username,passwor,sex,birthday,address) value(#{id},#{username},#{password},#{sex},#{birthday},#{address})
5.2 特殊总结
- parameterType:指定输入参数的类型
- resultType:指定输出结果的类型,在select中如果查询结果是集合,那么也表示集合中每个元素的类型
- 使用#{}:表示占位符,用来接收输入参数,类型可以是简单类型,pojo,HashMap等等 如果接收简单类型,#{}可以写成 value 或者其他名称 如果接收 pojo 对象值,通过 OGNL 读取对象中的属性值,即属性.属性.属性...的方式获取属性值
- 使用${}:表示一个拼接符,会引起 sql 注入,不建议使用 用来接收输入参数,类型可以是简单类型,pojo,HashMap等等 如果接收简单类型,${}里面只能是 value 如果接收 pojo 对象值,通过 OGNL 读取对象中的属性值,即属性.属性.属性...的方式获取属性值