MyBatis+Hibernate+JDBC对比分析
MyBatis目前作为持久层,用的最多,因为它符合互联网开发的变动性,实际开发中需求总会有这样的,那样的变动,MyBatis虽然没有Hibernate那么全自动化,而且对于开发人员的sql能力要求比较高,但是正是因为这样sql可以优化,业务也更容易扩展。
hibernate对于sql能力不是特别强的开发人员,是一个很好的利器,而且hibernate更面向对象,hibernate不适合开发高并发高访问量的应用,很简单不能sql优化,每次查询基本都要全表扫描,即便是有hql,但是过多的使用hql,反而破坏Hibernate的封装性,实际开发多联表查多个字段信息,有的时候一张表十几个字段,信息,另外一个表十几个,在另外一个表又十几个,对于Hibernate而言是个不小的挑战,对于性能要求不高,响应速度较慢的应用,同一时间段访问人不多的应用,还是很不错的,可以大幅度提高开发效率
OA办公,ERP等应用比较适合用Hibernate开发
像门户网站,博客这样的,访问量比较大,不只是前端优化,后台也要优化,所谓的后台主要是指sql优化,当然还有Java代码方面
MyBatis相对于JDBC而言,要好多了,至少它实现了解耦,sql语句和Java代码分离。
对于目前我个人博客项目,它的逆向工程让我不再重复单表的增删改查,节省比较多的时间,当然mybatis,虽然对于需求变动大的项目而言是比较符合实际的需要的,但是它的不好之处也显现出来了,就是对于不同的数据库需要书写不同的sql语句,可移植性差,而且它的插件用不好的话,导致性能也会下降
闲话不多说,贴一波个人编写的代码,温故而知新吧
我这边演示是JDK8+MAVEN工程
pom文件内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.example.test</groupId>
<artifactId>mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging> <dependencies>
<!-- hibernate核心包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.12.Final</version>
</dependency> <!--mybatis核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.1.1</version>
</dependency> <!-- 连接Mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency> <!--打印日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency> </dependencies> </project>
一、JDBC示例
package cn.jdbc; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet; public class JdbcExample { private static Connection getConnection() throws Exception {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/ssm";
String username = "root";
String password = "1234";
conn = DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace(); return null;
}
return conn; } public User getUserById(Integer Id) throws Exception {
/**
* 频繁的建立连接
*/
Connection connection = getConnection(); PreparedStatement ps = null; ResultSet rs = null; try {
/**
* Java代码和sql混合,不解耦,随着项目扩大,工作量会成倍增加
*/
ps = connection.prepareStatement("select * from `user` where id=?");
ps.setInt(1,Id);
rs = ps.executeQuery(); while(rs.next()) {
/**
* 指定获取的属性
* 实际开发中数据表的字段多,想要获取十几二十几个字段信息,如下rs.getInt("字段名")等等一系列不知要写多少个,随着代码量的增大,更不利于排错
*/
Integer id = rs.getInt("id");
String userName = rs.getString("user_name");
User user = new User();
user.setId(id);
user.setUserName(userName); return user; } } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
/**
* 频繁的关闭连接
*/
this.closeAll(rs, ps, connection);
} return null; } private void closeAll(ResultSet rs,PreparedStatement ps,Connection conn) { try { if(rs!=null && rs.isClosed()) {
rs.close();
} } catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} try { if(ps!=null && ps.isClosed()) {
ps.close();
} } catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} try { if(conn!=null && conn.isClosed()) {
conn.close();
} } catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} } public static void main(String[] args) throws Exception {
JdbcExample jdbc = new JdbcExample(); User user = jdbc.getUserById(1); System.out.println(user.getUserName());
} /**
* 从上述代码我们可以总结出Java连接JDBC的步骤
* 1.加载驱动
* 2.建立连接
* 3.通过PreparedStatement执行sql
* 4.由ResultSet返回结果集
* 5.关闭连接
*
* 使用传统的JDBC,存在如下问题:
* 1.不解耦,JDBC和sql混合一起,当需求变动,既要改Java代码,又要修改sql语句,工作量十分大,而在实际项目中,需求是不断变化的
* 2.频繁的建立连接,关闭连接,虽然后面有连接池,或者是将其封装成一个Utils,不过代码量依然会很大
*
* 说明:实际开发中并不用它,但是作为开发者必须要知道技术的应用场景和利弊,这样才能在开发中游刃有余
*/ }
JavaBean
说明:JavaBean在该例子中是适用所有的
数据表字段也就两个属性,大家自己建即可,这里就不贴了
package cn.jdbc; public class User {
private Integer Id;
private String userName;
public Integer getId() {
return Id;
}
public void setId(Integer id) {
Id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
} }
二、Hibernate示例
1.hibernate.cfg.xml主配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration>
<session-factory>
<!-- property 元素用于配置Hibernate中的属性
键:值
-->
<!-- hibernate.connection.driver_class : 连接数据库的驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!-- hibernate.connection.username : 连接数据库的用户名 -->
<property name="hibernate.connection.username">root</property> <!-- hibernate.connection.password : 连接数据库的密码 -->
<property name="hibernate.connection.password">1234</property> <!-- hibernate.connection.url : 连接数据库的地址,路径 -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/ssm</property> <!-- show_sql: 操作数据库时,会 向控制台打印sql语句 -->
<property name="show_sql">true</property> <!-- format_sql: 打印sql语句前,会将sql语句先格式化 -->
<property name="format_sql">true</property> <!-- hbm2ddl.auto: 生成表结构的策略配置
update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构.
如果存在表结构,并且表结构与实体一致,那么不做修改
如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
-->
<property name="hbm2ddl.auto">update</property> <!-- 数据库方言配置
org.hibernate.dialect.MySQLDialect (选择最短的)
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- hibernate.connection.autocommit: 事务自动提交 -->
<property name="hibernate.connection.autocommit">true</property> <!-- 将Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession -->
<property name="hibernate.current_session_context_class">thread</property> <!-- 引入ORM 映射文件
填写src之后的路径
-->
<mapping resource="cn/hibernate/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
2.User.hbm.xml文件
<hibernate-mapping> <!--
<class>:使用class元素定义一个持久化类。
name="cn.javass.user.vo.UserModel":持久化类的java全限定名;
table="tbl_user":对应数据库表名;
mutable="true":默认为true,设置为false时则不可以被应用程序更新或删除;
dynamic-insert="false":默认为false,动态修改那些有改变过的字段,而不用修改所有字段;
dynamic-update="false":默认为false,动态插入非空值字段;
select-before-update="false":默认为false,在修改之前先做一次查询,与用户的值进行对比,有变化都会真正更新; -->
<class name="cn.hibernate.User" table="user" dynamic-insert="true" dynamic-update="true"> <!--
<id>:定义了该属性到数据库表主键字段的映射。
name="userId":标识属性的名字;
column="userId":表主键字段的名字,如果不填写与name一样;
-->
<id name="Id">
<!-- <generator>:指定主键由什么生成,推荐使用uuid(随机生成唯一通用的表示符,实体类的ID必须是String),
native(让数据库自动选择用什么生成(根据底层数据库的能力选择identity,sequence或hilo中的一种)),
assigned(指用户手工填入,默认)。 -->
<generator class="native"/>
</id> <!--
<property>:为类定义一个持久化的javaBean风格的属性。
name="name":标识属性的名字,以小写字母开头;
column="name":表主键字段的名字,如果不填写与name一样;
update="true"/insert="true":默认为true,表示可以被更新或插入;
-->
<property name="userName" column="user_name" /> </class>
</hibernate-mapping>
3.HibernateExample.java
package cn.hibernate; import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; public class HibernateExample { private static SessionFactory sessionFactory; static { try {
Configuration cfg = new Configuration().configure("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } catch (Exception e) {
// TODO: handle exception e.printStackTrace();
}
} public static SessionFactory getSessionFactory() { return sessionFactory;
} }
4.TestHibernate.java
package cn.hibernate; import org.hibernate.Session; public class TestHibertnate { /**
* hibernate流程
*1.通过Configuration创建SessionFactory
*2.通过SessionFactory创建Session
*3.通过Session打开openSession
*4.通过session调用方法
*
*
*openSession和getCurrentSession的区别
*openSession创建session时autoCloseSessionEnabled参数为false,即在事物结束后不会自动关闭session,需要手动关闭,如果不关闭将导致session关联的数据库连接无法释放,最后资源耗尽而使程序挂掉。
*getCurrentSession创建session时autoCloseSessionEnabled,flushBeforeCompletionEnabled都为true,并且session会同sessionFactory组成一个map以sessionFactory为主键绑定到当前线程。
* @param args
*/
public static void main(String[] args) { Session session = null; try {
session = HibernateExample.getSessionFactory().openSession(); User user = session.get(User.class, 1);
System.out.println(user.getUserName());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
if(session!=null) {
session.close();
}
} }
}
三、MyBatis示例
1.MyBatisExample示例
package cn.mybatis; import java.io.IOException;
import java.io.InputStream; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisExample { private static SqlSessionFactory sqlSessionFactory = null; public static SqlSessionFactory getSqlSessionFactory() {
InputStream is = null;
if(sqlSessionFactory==null) { String resource = "mybatis-config.xml";
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(resource));
return sqlSessionFactory;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } return sqlSessionFactory;
} }
2.TestMyBatis.java
package cn.mybatis; import org.apache.ibatis.session.SqlSession; public class TestMyBatis { public static void main(String[] args) {
SqlSession sqlSession = null;
sqlSession = MyBatisExample.getSqlSessionFactory().openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);
/**
* 通过Main方法运行只能显示ID信息,不能显示userName的信息
* 这是因为resultType针对的字段和属性一致的情况,当数据表字段与JavaBean属性不一致时,要得到数据,需要使用resultMap
*/
System.out.println(user.getId()+"||"+user.getUserName()); }
}
3.UserMapper.java
package cn.mybatis; public interface UserMapper { User getUserById(Integer Id);
}
4.UserMapper.xml
<?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="cn.mybatis.UserMapper"> <!--
id 必须与对应接口方法一致
parameterType 参数类型可以是Map,String,Integer等等一大堆,但是必须要指定
resultType 适用场景:数据表字段和JavaBean实体属性一致
resultMap 适用场景:数据表字段和JavaBean实体属性不一致 --> <!-- <select id="getUserById" parameterType="Integer" resultType="cn.mybatis.User">
select id,user_name from `user` where id=#{Id}
</select> --> <select id="getUserById" parameterType="Integer" resultMap="users">
select id,user_name from `user` where id=#{Id}
</select> <!--
column对应数据表字段
property对应JavaBean属性
type 通常指返回类型 一般要写全限定名 不过只要在mybatis-config.xml配置别名扫描就不要写全名了
--> <resultMap type="User" id="users">
<id column="id" property="Id"/>
<result column="user_name" property="userName"/>
</resultMap> </mapper>
5.mybatis-config.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> <!-- 给cn.mybatis包下起别名 -->
<typeAliases>
<package name="cn.mybatis" />
</typeAliases> <!-- 对事务的管理和连接池的配置 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/ssm" />
<property name="username" value="root" />
<property name="password" value="1234" />
</dataSource>
</environment>
</environments> <!-- mapping 文件路径配置 -->
<mappers>
<mapper resource="cn/mybatis/UserMapper.xml" />
</mappers> </configuration>
MyBatis还有很多有待研究的,说到这,不得不提一个增强版本的MyBatis 称之为MyBatis Plus 可无缝结合Spring+SpringMVC,而且增删改查也不需要写,只需继承一个类即可
参考官网:http://mp.baomidou.com/
关于mybatis的逆向工程和动态代理,可以参考我的博客Java框架和MyBatis
MyBatis+Hibernate+JDBC对比分析的更多相关文章
- jdbc ,jdbcTemplate,MyBatis,Hibernate比较与分析
JDBC 1:jdbc(Java Data Base Connection 数据库连接)是一种用于执行sql语句的API,其中使用jdbc连接时需要的,Connection,Statement,Res ...
- MySQL 存储过程实例 与 ibatis/mybatis/hibernate/jdbc 如何调用存储过程
虽然MySQL的存储过程,一般情况下,是不会使用到的,但是在一些特殊场景中,还是有需求的.最近遇到一个sql server向mysql迁移的项目,有一些sql server的存储过程需要向mysql迁 ...
- Hibernate框架与Mybatis框架的对比
学习了Hibernate和Mybatis,但是一直不太清楚他们两者的区别的联系,今天在网上翻了翻,就做了一下总结,希望对大家有帮助! 原文:http://blog.csdn.net/firejuly/ ...
- mybatis及其与hibernate的对比
1.mybatis是支持普通SQL查询.存储过程.和高级映射的优秀持久层框架 它消除了JDBC代码和参数的手工设置,以及对结果集的检索 2.mybatis使用简单的XML或注解用于配置和原始映射,将接 ...
- jdbc,mybatis,hibernate各自优缺点及区别
先比较下jdbc编程和hibernate编程各自的优缺点. JDBC: 我们平时使用jdbc进行编程,大致需要下面几个步骤: 1,使用jdbc编程需要连接数据库,注册驱动和数据库信息 ...
- jdbc,mybatis,hibernate各自有优缺点以及区别
JDBC: 我们平时使用jdbc进行编程,大致需要下面几个步骤: 1,使用jdbc编程需要连接数据库,注册驱动和数据库信息 2,操作Connection,打开Statement对象 3,通过State ...
- Mybatis与Hibernate的对比
Mybatis与Hibernate的对比 工作中,用了一段Hibernate与Mybatis,也在此简单的聊上几句,希望对大家有帮助. Mybatis与Hibernate不同,它不完全是一个ORM框架 ...
- iBatis & myBatis & Hibernate 要点记录
iBatis & myBatis & Hibernate 要点记录 这三个是当前常用三大持久层框架,对其各自要点简要记录,并对其异同点进行简单比较. 1. iBatis iBatis主 ...
- Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案
转自http://www.cnblogs.com/fnz0/p/5713102.html 不知道自己什么时候才有这种钻研精神- -. 1 背景 系统中需要批量生成单据数据到数据库表,所以采用 ...
随机推荐
- [android] androidPN开源项目介绍
打开androidPN项目,会看到server和client两份代码 server部分 找到server的代码,开启服务,双击 bin/run.bat ,服务启动后监听127.0.0.1:7070端口 ...
- php编程规范整理
该规范对其他语言,部分是通用的标准....好吧,废话不多说啦,直入正题: 1.PHP 编程规范与编码习惯最主要的有以下几点: 1 文件说明 2 function 函数体说明 3 代码缩进 4 if省略 ...
- kafka结合Spark-streming的直连(Direct)方式
说明:此程序使用的scala编写 在spark-stream+kafka使用的时候,有两种连接方式一种是Receiver连接方式,一种是Direct连接方式. 两种连接方式简介: Receiver接 ...
- 终端复用软件 tmux
Tmux是一个优秀的终端复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权. Tmux 所使用的快捷键前缀默认是组合键 Ctrl-b(同时按下 Ctrl 键和 b 键). 技巧 ...
- 结合vue展示百度天气接口天气预报
HTML: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- Flume Source 实例
Flume Source 实例 Avro Source 监听avro端口,接收外部avro客户端数据流.跟前面的agent的Avro Sink可以组成多层拓扑结构. 1 2 3 4 5 6 7 8 9 ...
- mv,rm等命令出现unrecognized option提示的解决方法
出现这个提示,一般是由于命令操作的文件名最前面有"--"字符, 让命令误以为是--开头的长选项 解决: 命令后加上"--", shell把 -- 之后的参数当做 ...
- css,响应鼠标事件,文字变色
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- sass @function,@for,@mixin 的应用
项目前提: 不同的汽车显示不同的图片,一共9种汽车:每种汽车显示不同状态的图片,一共6种状态,所以一共会有54张图片 后台接口返回汽车种类分别为:1-9,汽车状态分别为:0-5 项目需求: 根据后台返 ...
- Ant使用及项目实践
1.简介 Ant 是一个 Apache 基金会下的跨平台的基于 Java 语言开发的构件工具.这是一个基于开放的操作系统构建和部署的工具,该工具需要从命令行执行. 2.特点 Ant 是基于 Java ...