四、Mybatis 学习
1、Mybatis入门及基本实现
1.1 Mybatis 与 Hibernate 对比
① 简介
MyBatis:持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
Hibernate:Hibernate是当前最流行的ORM框架之一,对JDBC提供了较为完整的封装。Hibernate的O/R Mapping实现了POJO 和数据库表之间的映射,以及SQL的自动生成和执行。
② 开发速度
难易度
Hibernate的真正掌握要比Mybatis困难,Hibernate比mybatis更加重量级一些。Mybatis框架相对简单很容易上手,但也相对简陋些。
开发工作量
Mybatis需要我们手动编写SQL语句,回归最原始的方式,所以可以按需求指定查询的字段,提高程序的查询效率。Hibernate也可以自己写SQL语句来指定需要查询的字段,但这样破坏了Hibernate封装以及简洁性。
③ 数据库移植性
Mybatis由于所有SQL都是依赖数据库书写的,所以扩展性,迁移性比较差。 Hibernate与数据库具体的关联都在XML中,所以HQL对具体是用什么数据库并不是很关心。
④ 缓存机制对比
相同点
Hibernate和Mybatis的二级缓存除了采用系统默认的缓存机制外,都可以通过实现你自己的缓存或为其他第三方缓存方案,创建适配器来完全覆盖缓存行为。
不同点
Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再在具体的表-对象映射中配置是那种缓存。MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。
两者比较
因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL。所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。而MyBatis在这一方面,使用二级缓存时需要特别小心。如果不能完全确定数据更新操作的波及范围,避免Cache的盲目使用。否则,脏数据的出现会给系统的正常运行带来很大的隐患。
⑤两者对比总结
两者相同点
- 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:小巧、方便、高效、简单、直接、半自动化
Hibernate:强大、方便、高效、复杂、间接、全自动化
参考自https://blog.csdn.net/jiuqiyuliang/article/details/45378065
1.2 Mybatis 基本实现
配置 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>
<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/demo?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/tcwong/pojo/UserMapper.xml"/>
</mappers>
</configuration>
pojo 类
public class User {
private Integer id;
private String name;
private String password;
private Integer age;
private String address;
public User() {
super();
}
public User(Integer id, String name, String password, Integer age, String address) {
super();
this.id = id;
this.name = name;
this.password = password;
this.age = age;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
[@Override](https://my.oschina.net/u/1162528)
public String toString() {
return "User [id=" + id + ", name=" + name + ", password=" + password + ", age=" + age + ", address=" + address
+ "]";
}
}
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="com.tcwong.pojo.User">
<select id="query" resultType="com.tcwong.pojo.User">
select * from user
</select>
<insert id="insert" parameterType="com.tcwong.pojo.User">
insert into user (name,password,age,address) values(#{name},#{password},#{age},#{address})
</insert>
<update id="update" parameterType="com.tcwong.pojo.User">
update user set name=#{name},password=#{password},age=#{age},address=#{address} where id=#{id}
</update>
<delete id="delete">
delete from user where id=#{id}
</delete>
</mapper>
编写测试类
public class Test {
@org.junit.Test
public void query() throws IOException {
//加载配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
//获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获取SqlSession对象
SqlSession session = factory.openSession();
//namespace+id
List<User> list = session.selectList("com.tcwong.pojo.User.query");
list.forEach((t)->System.out.println(t));
session.close();
}
@org.junit.Test
public void insert() throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession openSession = sqlSessionFactory.openSession();
User user = new User();
user.setName("susu");
user.setPassword("123456");
user.setAge(16);
user.setAddress("上海");
int num = openSession.insert("com.tcwong.pojo.User.insert", user);
System.out.println(num);
openSession.commit();
openSession.close();
}
@org.junit.Test
public void update() throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession openSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(1006);
user.setName("susu");
user.setPassword("123456");
user.setAge(16);
user.setAddress("上海");
int num = openSession.update("com.tcwong.pojo.User.update", user);
System.out.println(num);
openSession.commit();
openSession.close();
}
@org.junit.Test
public void delete() throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession openSession = sqlSessionFactory.openSession();
int num = openSession.delete("com.tcwong.pojo.User.delete", 1007);
System.out.println(num);
openSession.commit();
openSession.close();
}
}
控制台测试输出
注意:namespace和接口全路径名称相同,id和接口中的方法名相同