经过一周的Hibernate学习,我理解了作为以JPA为核心的持久层查询标准。JPA所涉及的思想为ORM(object relational mapping),它解释了为什么我们的实体关系要和数据库一一对应。这样做又有什么好处呢?当然更加方便的以面向对象的方式去对数据库进行操作,因为数据库存储的数据项很像一个对象。这样我们可以不需要使用传统的sql语句去对数据库进行查询,而是用JPA所代表的JPQL语句进行查询,这又大大的简化了开发人员学习sql语句的成本,这让我意识到,如果对sql语句不熟悉,那我也可以使用JPQL语句进行操作。关于这一点的好处将在后文叙述。
于是在这个思想的支持下,开始了以Hibernate的学习,因为Hibernate框架正是以JPA思想的实现。我很愿意去思考Hibernate和Mybatis比,这两种框架既然达成的目的都是一样的,并且所采用的思路均为ORM,为何还要去开发两种不同的框架呢?这是否造成了在技术选型的困惑呢?于是我将从这两个框架的比较为主线对这一周的Hibernate学习做个简要的总结。
1.比较配置文件:
<?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">
<!--mybatis的主配置文件-->
<configuration>
<!-- 配置环境-->
<environments default="mysql">
<!-- 配置mysql环境-->
<!-- default值与id值一样-->
<environment id="mysql">
<!-- 配置事务类型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源或连接池 三个连接池-->
<dataSource type="POOLED">
<!-- 配置连接数据库的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value=""/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/dennis/dao/IUserDao.xml"/>
</mappers>
</configuration>
这是mybatis的配置文件,从主配置文件上看,它配置了数据库的连接信息,连接池,事务控制信息,并且将Dao层的配置文件进行了关联。
<?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="com.dennis.dao.IUserDao">
<!-- 配置查询所有id值为IUserDao中的方法名-->
<select id="findAll" resultType="com.dennis.domain.User">
select * from user;
</select>
</mapper>
而sql语句就是放在Dao层的配置文件,在这里配置文件提供了查询语句的结果,所调用的方法,针对于谁的配置文件,这些信息方便了在service层中进行调用。
至于Hibernate框架,它只需要配置一个配置文件,位置通常放置于META-INF下。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!-- JTA是分布式任务管理 resource_local是本地事物管理-->
<persistence-unit name="Jpa" transaction-type="RESOURCE_LOCAL">
<!-- 由hibernate实现JPA接口-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- 可选配置 数据库连接信息-->
<properties>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="1"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/hibernate"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<!-- 是否显示信息-->
<property name="hibernate.show_sql" value="true"/>
<!-- 当表存在时先删除 再创建-->
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
JPA的配置文件需要规定由哪个框架实现的JPA接口,除此之外,当然还要将数据库连接信息,及个性化的配置写在上面。
比较了配置文件之后,会发现其实两个框架的使用上面各有各的特色,在配置完了配置文件后,我们还可以将Spring框架分别与这两个框架整合,与JPA的结合便催生出了Spring Data JPA。如果使用Spring框架,当然还要去配置一些额外信息,使得bean的获取更加便利。
比较了配置信息后,两个框架就开始显示出了差异性,细心的你可以发现问题,那就是在Hibernate中我没有使用SQL语句,那怎么去查询呢?
2.Hello World案例
public void test9(){
EntityManager manager = PersisUtil.getEntityManager();
EntityTransaction tx = manager.getTransaction();
tx.begin();
String jpql = "from Customer where custName like ?";
Query query = manager.createQuery(jpql);
query.setParameter(1,"%永%");
List list = query.getResultList();
for(Object li:list){
System.out.println(li);
}
tx.commit();
manager.close();
}
Hibernate框架可以将我们的查询语句写到Service层中,或者写到Dao接口,如果我们不写语句查询的话也可以,我们可以使用EntityManager封装的方法,比如persist等方法。还可以使用方法名称规则查询等。
public static void main(String[] args) throws Exception {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂 借助SqlSessionFactoryBuilder进行创建工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession sqlSession = factory.openSession();
//4.使用sqlSession创建Dao的代理类对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> all = userDao.findAll();
for (User user:all){
System.out.println(user);
}
//6.释放资源
sqlSession.close();
in.close();
}
Mybatis框架则必须使用Sql语句进行查询了,它没有为我们封装一些简单查询就可以获得结果的方法。比较两者会发现都使用了工厂模式获取对象,Mybatis中的设计模式更加丰富,它使用的是SqlSession对象进行查询,而Hibernate使用EntityManager进行查询。
3.灵活性方面
两个框架的简单查询方面,我认为Hibernate更胜一筹,它可以为我们直接提供findAll方法,并将结果封装给我们。而Mybatis还要写sql语句。但我们使用框架不可能总使用简单的语句进行查询,我们还需要对单表的条件查询,分页查询,动态查询,聚合函数查询,排序查询等。此外,还涉及到多表的查询,一对一,一对多,多对多等都涉及了这方面的问题。经过学习之后,发现Spring Data JPA框架中的Specification为我们实现的单表的多样化操作非常复杂,而Mybatis的sql语句和动态查询的配置非常方便。所以,这里我认为Mybatis框架更具有优势。对于多表查询双方都有优势,MyBatis的映射配置可以为我们实现多表联合查询,但由于联合查询的语句较为复杂,而Hibernate不需要写极为复杂的语句,只需要在实体类中用@oneToMany或@ManyToMany及@JoinTable/@JoinColumn就可以实现多表查询。同时也可以设置级联操作。要比MyBatis简单许多。至于延迟加载和缓存两个框架都可以进行简单的设置。