标签:
hibernate和mybatis都是orm的框架,首先贴一波自己对于这两个框架的理解,如果有错误欢迎指正:使用hibernate可以轻松实现po类到数据库表的映射,而且hibernate封装了sql,将传统的数据库操作更加偏向于面向对象想,开发者在操作数据库时不需要对数据库知识有很多的了解,因为hibernate会自动生成sql语句,这是hibernate的优点同时也是他的缺点,毕竟框架是面向程序开发,考虑到的是大部分使用场景,不可能对于sql语句做很多的优化,但是如果开发者使用hibernate的方法执行自己的sql语句的话,这也不是不可以实现,但是也会和项目整体的架构会有冲突,这也就是hibernate失去了使用他的意义,而mybatis允许开发者使用自己的sql语句,而且用户可以自己调优.,而且hibernate在缓存方面的支持较mybatis更加丰富,hibernate还有自己得日志记录,而mybatis则需要使用第三方日志jar文件,常用的是log4j,个人认为,hibernate和mybatis的使用场景有很大差别,至于使用哪种,完全在于开发者来选择,至于目前软件开发领域极度鄙视ssh追捧springmvc+spring+mybatis,我觉得两者都是很好的框架,关键是在于使用场景,完成所需功能,其实使用哪种开发流程都是一样的.
下面在贴一波,别人关于hibernate和mybatis优缺点的描述:
Hibernate的真正掌握要比Mybatis来得难些。Mybatis框架相对简单很容易上手,但也相对简陋些。个人觉得要用好Mybatis还是首先要先理解好Hibernate。
开发社区Hibernate 与Mybatis都是流行的持久层开发框架,但Hibernate开发社区相对多热闹些,支持的工具也多,更新也快,当前最高版本4.1.8。而Mybatis相对平静,工具较少,当前最高版本3.2。
开发工作量Hibernate和MyBatis都有相应的代码生成工具。可以生成简单基本的DAO层方法。
针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程。
2、系统调优对比Hibernate的调优方案MyBatis在Session方面和Hibernate的Session生命周期是一致的,同样需要合理的Session管理机制。MyBatis同样具有二级缓存机制。 MyBatis可以进行详细的SQL优化设计。
SQL优化方面Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。而Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。
Hibernate HQL语句的调优需要将SQL打印出来,而Hibernate的SQL被很多人嫌弃因为太丑了。MyBatis的SQL是自己手动写的所以调整方便。但Hibernate具有自己的日志统计。Mybatis本身不带日志统计,使用Log4j进行日志记录。
扩展性方面Hibernate与具体数据库的关联只需在XML文件中配置即可,所有的HQL语句与具体使用的数据库无关,移植性很好。MyBatis项目中所有的SQL语句都是依赖所用的数据库的,所以不同数据库类型的支持不好。
3、对象管理与抓取策略对象管理Hibernate 是完整的对象/关系映射解决方案,它提供了对象状态管理(state management)的功能,使开发者不再需要理会底层数据库系统的细节。也就是说,相对于常见的 JDBC/SQL 持久层方案中需要管理 SQL 语句,Hibernate采用了更自然的面向对象的视角来持久化 Java 应用中的数据。
换句话说,使用 Hibernate 的开发者应该总是关注对象的状态(state),不必考虑 SQL 语句的执行。这部分细节已经由 Hibernate 掌管妥当,只有开发者在进行系统性能调优的时候才需要进行了解。
而MyBatis在这一块没有文档说明,用户需要对对象自己进行详细的管理。
抓取策略Hibernate对实体关联对象的抓取有着良好的机制。对于每一个关联关系都可以详细地设置是否延迟加载,并且提供关联抓取、查询抓取、子查询抓取、批量抓取四种模式。 它是详细配置和处理的。
而Mybatis的延迟加载是全局配置的。
4、缓存机制对比Hibernate缓存Hibernate一级缓存是Session缓存,利用好一级缓存就需要对Session的生命周期进行管理好。建议在一个Action操作中使用一个Session。一级缓存需要对Session进行严格管理。
Hibernate二级缓存是SessionFactory级的缓存。 SessionFactory的缓存分为内置缓存和外置缓存。内置缓存中存放的是SessionFactory对象的一些集合属性包含的数据(映射元素据及预定SQL语句等),对于应用程序来说,它是只读的。外置缓存中存放的是数据库数据的副本,其作用和一级缓存类似.二级缓存除了以内存作为存储介质外,还可以选用硬盘等外部存储设备。二级缓存称为进程级缓存或SessionFactory级缓存,它可以被所有session共享,它的生命周期伴随着SessionFactory的生命周期存在和消亡。
5、优势对比
Mybatis优势hibernate说明文档:就不贴了,很好找,直接百度即可
言归正传,第一个hibernate程序,由于我也刚学,网上也很少找到,mybatis关于数据库连接池的代码配置,这里就不贴,不使用数据库连接池了:
第一步:导入jar包:mybatis-3.2.3.jar,数据库驱动,这里采用的是MySQL数据库
第二步,编写po类和映射文件,可以使用映射文件操作数据库,也可使用接口实例实现操作:
po类:
package com.leige.domain; public class Student { private Integer sid; private String name; private Integer age; setter.. getter... }
<?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"> <!-- 命名空间就是实现sql的隔离,把对于一个对象的操作sql语句放在一个命名空间中 这里的调用查询就是Student.selectStudentById --> <mapper namespace="Student"> <!-- 按照sid查询数据库 注意在使用简单po类的简单名称时,前提是在configuration中配置了别名 <typeAliases> <typeAlias alias="Student" type="com.leige.domain.Student"/> </typeAliases> --> <select id="selectStudentById" parameterType="int" resultType="Student"> <![CDATA[ select * from student where sid = #{sid} ]]> </select> <select id="selectStudentByName" parameterType="java.lang.String" resultType="Student"> <!-- '%${value}%'表示字符串拼接,注意占位符的名称不能叫做po类的属性名,出了id除外,不然会报错 There is no getter for property named 'xxx' in 'class java.lang.String' 不过不建议使用,会产生sql注入 --> <![CDATA[ select * from student where name like '%${value}%' ]]> </select> <!-- 增加 --> <insert id="insertStudent" parameterType="Student"> <!-- 配置主键自增返回,必须和插入语句一起执行才能使用 order:表示语句相对于insert的执行顺序 resultType:返回结果类型,必须配置 mysql的函数SELECT LAST_INSERT_ID()可以查询 --> <selectKey keyProperty="sid" order="AFTER" resultType="int"> <![CDATA[ SELECT LAST_INSERT_ID() ]]> </selectKey> <!-- 非自增主键返回 <selectKey keyProperty="sid" order="AFTER" resultType="java.lang.String"> <![CDATA[ SELECT UUID() ]]> </selectKey> --> <![CDATA[ insert into student(sid,name,age) values(#{sid},#{name},#{age}) ]]> </insert> <!-- 删除 --> <delete id="deleteStudentById" parameterType="int"> <![CDATA[ delete from student where sid=#{sid} ]]> </delete> <!-- 更新 --> <delete id="updateStudent" parameterType="Student"> <![CDATA[ update student set name=#{name},age=#{age} where sid=#{sid} ]]> </delete> </mapper>
package com.leige.domain; import java.util.List; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.SelectKey; import org.apache.ibatis.annotations.Update; public interface StudentMapper { //id查找 @Select("select * from student where sid=#{sid}") public Student selectStudent(Integer id); //添加 @SelectKey(before=false,keyProperty="sid",statement="SELECT LAST_INSERT_ID()", resultType =int.class) @Select("insert into student(sid,name,age) values(#{sid},#{name},#{age})") public void addStudent(Student student); //查找多个 @Select("select * from student where name like'%${value}%'") public List<Student> selectStudentByName(String name); //删除 @Delete("delete from student where sid=#{value}") public void deleteStudentById(Integer sid); //更新 @Update("update student set name=#{name},age=#{age} where sid=#{sid}") public void update(Student student); }
<?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> <!-- 加载jdbcproperties 要写在configuration和environment之间 --> <properties resource="com/leige/config/jdbcInfo.properties"></properties> <!-- 别名声明,告诉mybatis,Student对应的类类型 使其能将Student这个字符和Student类对应起来 类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余 即在任何需要使用com.leige.domain.Student的地方都可以使用Student --> <typeAliases> <typeAlias alias="Student" type="com.leige.domain.Student"/> </typeAliases> <!-- 环境配置,数据库连接参数 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <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> <!-- 将操作sql集合加入配置文件 --> <mappers> <mapper resource="com/leige/domain/StudentMapper.xml"/> </mappers> </configuration>jdbc配置参数:
driver=com.mysql.jdbc.Driver url=jdbc\:mysql\:///test username=root password=
package com.leige.test; 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; import org.junit.Test; /** * @author sqlsession工具类 * */ public class SqlUtils { static SqlSessionFactory factory; //静态加载session工厂 static{ InputStream inputStream; try { inputStream = Resources.getResourceAsStream("com/leige/config/configuration.xml"); //1:实例化sqlsessionfactory工厂 factory= new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { } } public static SqlSession getSession() { try{ //开启session return factory.openSession(); }catch(Exception e){ throw new RuntimeException(e); } } /** * @param session * @param mapper * @return * 保证会话session一致,所以当做参数传过来 */ public static Object getmaMapper(SqlSession session,Class mapper){ //注册映射接口 factory.getConfiguration().addMapper(mapper); //返回操作实例 return session.getMapper(mapper); } }
package com.leige.test; 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.leige.domain.Student; import com.leige.domain.StudentMapper; public class App { /** * @throws 根据id查询单个对象 */ @Test public void fun() throws Exception{ InputStream inputStream=Resources.getResourceAsStream("configuration.xml"); //1:实例化sqlsessionfactory工厂 SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(inputStream); //2:注册接口 //factory.getConfiguration().addMapper(StudentMapper.class); //3:开启session SqlSession session=factory.openSession(); //4:1操作数据库有两种操作方式一种是,命名空间加命名语句执行 //System.out.println(session.selectOne("Student.selectStudent",1)); /*第二种是使用操作接口操作数据库 * 但是需要先注册接口,且接口需要用注解声明操作语句 * 即在接口上注册执行时所需要的语句@Select("select * from student where sid=#{id}") * */ //注册接口 factory.getConfiguration().addMapper(StudentMapper.class); //得到映射器实例 StudentMapper studentMapper=(StudentMapper) session.getMapper(StudentMapper.class); //查询数据库 System.out.println(studentMapper.selectStudent(1)); session.close(); } /** * 测试查找多个 */ @Test public void testFindByName(){ try { //通过工具类得到session SqlSession session=SqlUtils.getSession(); List<Student> students=null; //第一种方式:命名空间查找,也可以使用映射实例查找,selectList查找多个 // students=session.selectList("Student.selectStudentByName", "leige"); //第二种方式 StudentMapper mapper= (StudentMapper) SqlUtils.getmaMapper(session,StudentMapper.class); students=mapper.selectStudentByName("leige"); //打印信息 for(Student stu:students) System.out.println(stu); } catch (Exception e) { // TODO Auto-generated catch block System.out.println(e); } } /** * 测试增加 */ @Test public void testInsert(){ //通过工具类得到session SqlSession session=SqlUtils.getSession(); Student student=new Student(); student.setAge(22); student.setName("leige3"); //第一種方式:执行插入,使用xml配置中sql参数 //session.insert("Student.insertStudent",student); //第二種插入,使用接口文件中的sql参数 StudentMapper mapper=(StudentMapper) SqlUtils.getmaMapper(session, StudentMapper.class); mapper.addStudent(student); //输出返回的主键 System.out.println(student.getSid()); //注意查询的时候不需要提交,做增删改时需要提交才会生效 session.commit(); //关闭session session.close(); } /** * 测试删除 */ @Test public void testDelete(){ //获得session SqlSession session=SqlUtils.getSession(); //第一種方式:执行删除,使用xml配置中sql参数 session.delete("Student.deleteStudentById",12); //第二種删除,使用接口文件中的sql参数 StudentMapper mapper=(StudentMapper) SqlUtils.getmaMapper(session, StudentMapper.class); mapper.deleteStudentById(13); //提交 session.commit(); //关闭 session.close(); } /** * 测试更新 */ @Test public void testupdate(){ //获得session SqlSession session=SqlUtils.getSession(); //这里就不查询数据库了,直接修改得了 Student student=new Student(); student.setSid(1); student.setAge(21); student.setName("leige23"); //第一種方式:执行更新,使用xml配置中sql参数 //session.update("Student.updateStudent",student); //第二中更新,使用接口文件中的sql参数 StudentMapper mapper=(StudentMapper) SqlUtils.getmaMapper(session, StudentMapper.class); mapper.update(student); //提交 session.commit(); //关闭 session.close(); } }
标签:
原文地址:http://blog.csdn.net/do_bset_yourself/article/details/51242771