Hibernate与Mybatis对比

在了解SSH中Hibernate之后,与另一SSM框架中的Mybatis相比确实缺少一定的灵活性。根据各种大神反馈来看,Hibernate与Mybatis的优缺点如下:

整体比较两者相同点

  • Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。

  • Hibernate和MyBatis都支持JDBC和JTA事务处理。

Hibernate优势

  • Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
  • Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
  • Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
  • Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。

Mybatis优势

  • MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
  • MyBatis容易掌握,而Hibernate门槛较高。

下面通过例子来看看:

Mybatis的全局控制文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?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>

<settings>
<!-- Globally enables or disables any caches configured in any mapper under this configuration -->
<!--该配置影响的所有映射器中配置的缓存的全局开关。-->
<setting name="cacheEnabled" value="true"/>
<!-- Sets the number of seconds the driver will wait for a response from the database -->
<!--设置超时时间,它决定驱动等待数据库响应的秒数。-->
<setting name="defaultStatementTimeout" value="3000"/>
<!-- Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn -->
<!--是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- Allows JDBC support for generated keys. A compatible driver is required.
This setting forces generated keys to be used if set to true,
as some drivers deny compatibility but still work -->
<!--允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。-->
<setting name="useGeneratedKeys" value="true"/>
</settings>

<!-- Continue going here -->

<environments default="development">
<environment id="development">
<transactionManager type="jdbc"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/test_db?serverTimeZone=UTC&amp;useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="mapper/GetStudentInfo.xml"/>
</mappers>

</configuration>

映射的学生类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import java.sql.Date;

/**
* Created by lollipop on 07/12/2016.
*/
public class Student {
private int sid; /*学号*/
private String name; /*姓名*/
private String gender; /*年龄*/
private String address; /*地址*/
private String phone; /*电话*/
private Date birthday; /*出生日期*/

public Student() {
}

public Student(String name, String gender, String address, String phone, Date birthday) {
this.name = name;
this.gender = gender;
this.address = address;
this.phone = phone;
this.birthday = birthday;
}

public Student(int sid, String name, String gender, String address, String phone, Date birthday) {
this.sid = sid;
this.name = name;
this.gender = gender;
this.address = address;
this.phone = phone;
this.birthday = birthday;
}

public int getSid() {
return sid;
}

public Student setSid(int sid) {
this.sid = sid;
return this;
}

public String getName() {
return name;
}

public Student setName(String name) {
this.name = name;
return this;
}

public String getGender() {
return gender;
}

public Student setGender(String gender) {
this.gender = gender;
return this;
}

public String getAddress() {
return address;
}

public Student setAddress(String address) {
this.address = address;
return this;
}

public String getPhone() {
return phone;
}

public Student setPhone(String phone) {
this.phone = phone;
return this;
}

public Date getBirthday() {
return birthday;
}

public Student setBirthday(Date birthday) {
this.birthday = birthday;
return this;
}

@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", address='" + address + '\'' +
", phone='" + phone + '\'' +
", birthday=" + birthday +
'}';
}
}

Mybatis主要将相应的配置文件中对数据库的操作,映射到相应的接口中的方法,通过接口中的方法来完成相应的数据库操作。

接口代码:

1
2
3
4
5
6
7
8
9
10
11
/**
* Created by lollipop on 07/12/2016.
*/
public interface GetStudentInfo {
Student getStudent(int sid);
void updateStudent(Student student);
void deleteStudent(int sid);
void addStudent(Student student);

}

接口相应的映射配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?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="GetStudentInfo">
<insert id="addStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="sid">
INSERT INTO STUDENT (NAME, GENDER, ADDRESS, PHONE, BIRTHDAY)
VALUE (#{name}, #{gender}, #{address}, #{phone}, #{birthday})
</insert>

<update id="updateStudent" parameterType="Student">
UPDATE STUDENT
SET NAME = #{name}, gender = #{gender}, address = #{address}, phone = #{phone}, birthday = #{birthday}
WHERE sid = #{sid}
</update>

<delete id="deleteStudent" parameterType="int">
DELETE FROM STUDENT
WHERE SID = #{sid}
</delete>

<select id="getStudent" resultType="Student" parameterType="int">
SELECT
SID,
NAME,
GENDER,
ADDRESS,
PHONE,
BIRTHDAY
FROM STUDENT
WHERE SID = #{sid}
</select>
</mapper>

具体的Main类对,Mybatis进行基本的数据库增,删,改,查操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.sql.Date;

/**
* Created by lollipop on 07/12/2016.
*/
public class Main {
public static void main (String args[]) {
String resource = "conf.xml";
InputStream is = Main.class.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession(true);
try{

GetStudentInfo getStudentInfo = session.getMapper(GetStudentInfo.class);
/*查询*/
Student student = getStudentInfo.getStudent(1);
System.out.println(student);


/*插入*/
student = new Student("小智","男","荆州","123456789", Date.valueOf("2000-08-08"));
getStudentInfo.addStudent(student);


/*清除*/
getStudentInfo.deleteStudent(student.getSid());

/*更新*/
student.setName("小猪");
getStudentInfo.updateStudent(student);
}finally {
session.close();
}

}
}

接下来,我们来看看Hibernate是怎么实现对数据库中数据进行增,删,改,查操作的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package Study;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Iterator;
import java.util.List;

/**
* Created by lollipop on 02/12/2016.
*/
public class TestStudent {
private Session session;
private SessionFactory sessionFactory;
private Transaction transaction;

@Before
public void init() {
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}

@Test
public void test() {

/*添加*/
StudentEntity student = new StudentEntity(16, "王子", "男", "北京", "16", Date.valueOf("1996-10-01"));
session.save(student);

/*删除数据库中的表有满足属性为16的学生*/
StudentEntity delStudent = session.load(StudentEntity.class, 16);

session.delete(delStudent);


/*指定对象删除操作*/
// 删除sid 为 2的数据
StudentEntity studentEntity2 = new StudentEntity();
studentEntity2.setSid(2);
session.delete(studentEntity2);




// 使用下面语句会报错 但使用上面则正确
// session.delete(new StudentEntity().setSid(2));


// 下面引号部分 为参数(from 类)





/*遍历打印*/
Query query = session.createQuery("from StudentEntity ");
List userList = query.list();

System.out.println("利用foreach语句输出表中信息");
for (Object s : userList) {
StudentEntity ste = (StudentEntity) s;
System.out.println(ste.toString());
}
System.out.println("");
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println("");
System.out.println("利用迭代器输出表中信息");
for (Iterator iterator = userList.iterator(); iterator.hasNext(); ) {
StudentEntity ste = (StudentEntity) iterator.next();
System.out.println(ste.toString());
}

/*更新*/
StudentEntity studentEntity = session.load(StudentEntity.class,1);
studentEntity.setGender("女");
session.update(studentEntity);

}

@After
public void destroy() {
transaction.commit();
session.close();
sessionFactory.close();

}
}

通过对比明显发现,Mybatis比Hibernate灵活得多,用户可以根据自己的编写的SQL语句对数据库进行操作,这也同时要求程序猿,要更加熟练的掌握相关的SQL语句。