Mybatis本是apache的一个开源项目ibatis,2010年这个项目由apache software foundation迁移到了google code,并改名为Mybatis。2013年11月迁移到github。
Mybatis是一个优秀的持久层框架,它对jdbc操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、CallableStatement)配置起来,并通过Java对象和statement中的SQL进行映射,生成最终执行的SQL语句,最后由Mybatis框架执行SQL并将结果映射成Java对象并返回。
使用jdbc的步骤:
加载数据库驱动
创建并获取数据库链接
创建jdbc statement对象
设置SQL语句
设置SQL语句中的参数(使用preparedStatement)
通过statement执行SQL并获取结果
对SQL执行结果进行解析处理
释放资源(resultSet、preparedStatement、connection)
例:
public class JdbcTest { public static void main(String[] args) { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { Class.forName("com.mysql.jdbc.Driver"); connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school?characterEncoding=UTF-8", "root", "root"); statement = connection.createStatement(); String sql = "select * from student where age = 18"; resultSet = statement.executeQuery(sql); while(resultSet.next()){ System.out.println(resultSet.getString("sname")); } } catch (Exception e) { e.printStackTrace(); } finally { if(resultSet != null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(statement != null){ try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(connection != null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
使用jdbc的问题:
(1)数据库连接创建、释放频繁会造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可以解决此问题。
(2)SQL语句在代码中硬编码,造成代码不易维护,实际使用中SQL变化的可能性较大,SQL变动需要改变Java代码。
(3)使用preparedStatement向占位符传参数也存在硬编码,因为SQL语句的where条件不一定,可能多也可能少,修改SQL还要修改代码,系统不易维护。
(4)对结果集解析同样存在硬编码(查询列名),SQL变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
1. Mybatis配置
SqlMapConfig.xml。此文件作为Mybatis的全局配置文件,配置了Mybatis的运行环境等信息。
mapper.xml文件。即SQL映射文件,文件中配置了操作数据库SQL语句。此文件需要再SqlMapConfig.xml中加载。
2. 通过Mybatis环境等配置信息构造SQLSessionFactory,即会话工厂。
3. 由会话工厂创建SqlSession,即会话,操作数据库需要通过SqlSession进行。
4. Mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器,一个是缓存执行器。
5. Mapped Statement也是Mybatis一个底层封装对象,它包装了Mybatis配置信息及SQL映射信息等。mapper.xml文件中一个SQL对应一个Mapped Statement对象,SQL的id即使Mapped Statement的id。
6. Mapped Statement对SQL执行的输入参数进行定义,包括HashMap、基本类型、pojo。Executor通过Mapped Statement在执行SQL前将输入Java对象映射至SQL中,输入参数映射就是jdbc编程中对PreparedStatement设置参数。
7. Mapped Statement对SQL执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行SQL后将输出结果映射至Java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
8.
1. 添加依赖
mysql mysql-connector-java 5.1.32 org.mybatis mybatis 3.2.8 junit junit 4.12
2. 创建SqlMapConfig.xml
SqlMapConfig.xml是Mybatis核心配置文件,配置文件内容为数据源、事务管理。
3. 创建pojo
pojo类作为Mybatis进行SQL映射使用,pojo类通常与数据库表对应,数据库user表如下:
CREATE TABLE user ( id INT(10) NOT NULL auto_increment, username VARCHAR(32) NOT NULL COMMENT '用户名', birthday DATE DEFAULT NULL COMMENT '生日', sex VARCHAR(2) DEFAULT NULL COMMENT '性别', address VARCHAR(256) DEFAULT NULL COMMENT '地址', PRIMARY KEY (id) ) ENGINE=INNODB DEFAULT CHARSET=utf8;
User.java如下:
public class User { private int id; private String username; private Date birthday; private String sex; private String address; /* get/set/toString() */ ...
4. 创建SQL映射文件
User.xml
5. 测试程序
测试程序步骤:
(1)创建SqlSessionFactoryBuilder对象
(2)加载SqlMapConfig.xml配置文件
(3)创建SqlSessionFactory对象
(4)创建SqlSession对象
(5)执行SqlSession对象执行查询,获取结果User
(6)打印结果
(7)释放资源
public class MybatisTest { private SqlSessionFactory sqlSessionFactory = null; @Before public void init() throws IOException { //1. 创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //2. 加载sqlMapConfig.xml配置文件 InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); //3. 创建SqlSessionFactory对象 sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); } @Test public void testQueryUserById(){ //4. 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //5. 执行Sqlsession对象进行查询,获取结果User //第一个参数是User.xml中statement的id,第二个参数是执行sql需要的参数 User user = sqlSession.selectOne("queryUserById", 1); //6. 打印结果 System.out.println(user); //7. 释放资源 sqlSession.close(); } }
输出:
User{id=1, username='张三', birthday=Tue Oct 31 00:00:00 GMT+08:00 2017, sex='男', address='北京'}
6. #{}和${}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行Java类型和jdbc类型转换。#{}可以有效防止SQL注入。#{}可以接收简单类型或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其他名称。
7. parameteType和resultType
parameterType:指定输入参数类型,Mybatis通过ognl从输入对象中获取参数值拼接在SQL中。
resultType:指定输出结果类型,Mybatis将SQL查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中。
8. mysql自增主键返回
查询id的sql:SELECT LAST_INSERT_ID()
# selectKey标签实现主键返回
# keyColumn:主键对应的表中的哪一列
# keyProperty:主键对应的pojo的哪一个属性
# order:设置在执行insert语句前执行查询id的sql,还是在执行insert语句之后执行查询id的sql
SELECT LAST_INSERT_ID()
INSERT INTO user (username, birthday, sex, address) values (#{username}, #{birthday}, #{sex}, #{address})