转自http://www.cnblogs.com/selene/p/4604605.html
话不多说,先看看原始的JDBC程序代码,看看这样的代码存在什么样子的问题。
package com.utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * @ClassName: JdbcTest * @Description: TODO(原始的JDBC操作数据库) * @author warcaft * @date 2015-6-27 下午3:31:22 * */ public class JdbcTest { public static void main(String[] args) { // 数据库连接 Connection connection = null; // 预编译的Statement,使用预编译的Statement提高数据库性能 PreparedStatement preparedStatement = null; // 结果 集 ResultSet resultSet = null; try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); // 通过驱动管理类获取数据库链接 connection = DriverManager .getConnection( "jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root"); // 定义sql语句 ?表示占位符 String sql = "select * from t_user where username = ?"; // 获取预处理statement preparedStatement = connection.prepareStatement(sql); // 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值 preparedStatement.setString(1, "王五"); // 向数据库发出sql执行查询,查询出结果集 resultSet = preparedStatement.executeQuery(); // 遍历查询结果集 while (resultSet.next()) { System.out.println(resultSet.getString("id") + " " + resultSet.getString("username")); } } catch (Exception e) { e.printStackTrace(); } finally { // 释放资源 if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
上面代码的问题总结:
1.数据库连接,使用时就创建,不适用时李记食坊,对数据库进行频繁的连接开启和关闭,造成数据库资源浪费,影像数据库性能。
解决方案:使用数据库连接池管理数据库连接
2.将sql语句硬编码到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护。
解决方案:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。
3.向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。
解决方案:将sql语句及占位符号和参数全部配置在xml中。
4.从resultSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护。
解决方案:将查询的结果集,自动映射成java对象。
MyBatis框架
MyBatis是什么?(下载地址:https://github.com/mybatis/mybatis-3/releases)
MyBatis本来是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到google code,并且改名MyBatis,实质上MyBatis对ibatis进行一些改进。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要管子SQL本身,二不需要花费精力去处理例如注册驱动,创建connection,创建statement,手动设置参数,结果集检索等jdbc复杂飞过程代码。
MyBatis通过xml或注解的方式将要执行的各种statement(statement,preparedstatement,CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果英社称java对象并返回。
MyBatis架构图
1.mybatis配置
SqlMapConfig.xml,此文件座位mybatis的全局配置文件,配置了mybatis的运行环境信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2.通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂。
3.由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4.mabatis底层自定义了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通过MappedStatement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7.Mapped Statement对sql执行输出结果进行定义,包括HashMap,基本类型,pojo,Executor通过Mapped Statement在执行sql后将输出结果映射到java对象中,输出结果映射过程相当于jdbs编程中对结果的解析处理过程。
MyBatis入门程序
1.需求:(1)根据用户id查询用户信息,(2)根据用户名称模糊查询用户信息(3)添加用户(4)更新用户
2.环境:java环境,JDK1.8,eclipse,MySql5.6.34
3.代码
先看结构
package com.mybatis.entity; public class User { private String student_id; private String student_name; private String card_id; private String student_class; private String sex; private String password; private String perovince; private String address; private String tel; private String interests; public String getStudent_id() { return student_id; } public void setStudent_id(String student_id) { this.student_id = student_id; } public String getStudent_name() { return student_name; } public void setStudent_name(String student_name) { this.student_name = student_name; } public String getCard_id() { return card_id; } public void setCard_id(String card_id) { this.card_id = card_id; } public String getStudent_class() { return student_class; } public void setStudent_class(String student_class) { this.student_class = student_class; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getPerovince() { return perovince; } public void setPerovince(String perovince) { this.perovince = perovince; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } public String getInterests() { return interests; } public void setInterests(String interests) { this.interests = interests; } @Override public String toString(){ return "学生 [姓名="+ student_name + "学号=" + student_id + "身份证号=" + card_id + "班级=" + student_class + "性别=" + sex + "密码=" + password + "籍贯=" + perovince + "住址=" + address + "电话=" + tel + "爱好=" + interests +"]"; } }
package com.mybatis.service; import java.io.IOException; import java.io.InputStream; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import com.mybatis.entity.User; public class MybatisService { //根据id查询用户信息,得到一条记录结果 @Test public void findUserByIdTest(){ //mybatis的配置文件 String resource = "SqlMapConfig.xml"; InputStream inputStream = null; SqlSession sqlSession = null; try{ inputStream = Resources.getResourceAsStream(resource); //1.创建会话工厂,传入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.通过工厂得到SqlSession sqlSession = sqlSessionFactory.openSession(); //3.通过sqlSession操作数据库 User user = sqlSession.selectOne("test.findUserById","001"); System.out.println(user.toString()); }catch(IOException e){ e.printStackTrace(); }finally{ if(sqlSession != null){ sqlSession.close(); } if(inputStream != null){ try{ inputStream.close(); }catch(IOException e){ e.printStackTrace(); } } } } //根据姓名 @Test public void findUserByNameTest(){ String resource = "SqlMapConfig.xml"; InputStream inputStream = null; SqlSession sqlSession = null; try{ inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(); List<User> list = sqlSession.selectList("test.findUserByName", "小"); System.out.println(list); }catch(IOException e){ e.printStackTrace(); }finally{ if(sqlSession != null){ sqlSession.close(); } if(inputStream != null){ try{ inputStream.close(); }catch(IOException e){ e.printStackTrace(); } } } } //添加用户 @Test public void insertUserTest(){ //mybatis的配置文件 String resource = "SqlMapConfig.xml"; InputStream inputStream = null; SqlSession sqlSession = null; try{ inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(); User user = new User(); user.setAddress("宿州"); user.setCard_id("987456123"); user.setInterests("读书"); user.setPassword("654"); user.setPerovince("安徽"); user.setSex("男"); user.setStudent_class("6"); user.setStudent_id("004"); user.setStudent_name("张柳"); user.setTel("156987644321"); sqlSession.insert("test.insertUser", user); sqlSession.commit(); System.out.println(user.getStudent_id()); }catch(IOException e){ e.printStackTrace(); }finally{ if(sqlSession != null){ sqlSession.close(); } if(inputStream != null){ try{ inputStream.close(); }catch(IOException e){ e.printStackTrace(); } } } } //根据id删除用户 @Test public void deleteUserTest(){ //mybatis的配置文件 String resource = "SqlMapConfig.xml"; InputStream inputStream = null; SqlSession sqlSession = null; try{ inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(); sqlSession.delete("test.deleteUser","004"); sqlSession.commit(); }catch(IOException e){ e.printStackTrace(); }finally{ if(sqlSession!=null){ sqlSession.close(); } if(inputStream != null){ try{ inputStream.close(); }catch(IOException e){ e.printStackTrace(); } } } } }
log4j.properties
#Global logging configuration
#在开发的环境下,日志级别要设置成DEBUG,生产环境要设置成info或error
log4j.rootLogger=DEBUG,stdout
#Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
SqlMapConfig.xml
<?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> <!-- 和spring整合后,environment配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理,事务控制由mybatis管理 --> <transactionManager type="JDBC"/> <!-- 数据库连接池,由mybatis管理 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/selective-courses-system?characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="logan123"/> </dataSource> </environment> </environments> <!-- 加载映射文件 --> <mappers> <mapper resource="sqlmap/User.xml"/> </mappers> </configuration>
这是执行结构
mybatis和Hibernate的本质区别于应用场景
hibernate:是一个标准ORM框架(对象关系映射),入门门槛较高的,不需要程序写sql,sql语句自动生成了,对sql语句进行优化、修改比较困难的。
应用场景:
适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。。
mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。
应用场景:
适用与需求变化较多的项目,比如:互联网项目。