mybatis官网:http://www.mybatis.org/mybatis-3/zh/index.html
Github源码:https://github.com/mybatis/mybatis-3
Mybatis是什么
- MyBatis 是一款优秀的持久层ORM框架
- 它内部封装了 jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement 等繁杂的过程。
- 它支持定制化SQL、存储过程以及高级映射。
- MyBatis 避免了几乎所有的 JDBC代码和手动设置参数以及获取结果集,它可以使用简单的XML或注解来配置和映射SQL信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
ORM是什么
Object relational mapping,简称ORM,对象-关系映射。
用来把对象模型表示的对象映射到基于SQL 的关系模型数据库结构中去。
这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的 SQL 语句打交道,只需简单的操作实体对象的属性和方法 。ORM 技术是在对象和关系之间提供了一条桥梁,前台的对象型数据和数据库中的关系型的数据通过这个桥梁来相互转化。
MyBatis和Hibernate对比
对比项 | Mybatis | Hibernate |
---|---|---|
市场占有率 | 高 | 高 |
适合的行业 | 互联网 电商 项目 | 传统的(ERP CRM OA) |
性能 | 高 | 低 |
Sql灵活性 | 高 | 低 |
学习门槛 | 低 | 高 |
Sql配置文件 | 全局配置文件、映射文件 | 全局配置文件、映射文件 |
ORM | 半自动化 | 完全的自动化 |
数据库无关性 | 低 | 高 |
JDBC的问题
- 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题
- Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码
- 使用preparedStatement向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护
- 对结果集解析存在硬编码(查询列名),sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成 pojo 对象解析比较方便
入门案例(增删该查)
- 依赖
<dependencies>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
- 配置文件
# resources/db.properties
db.username=root
db.password=
db.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
db.driver=com.mysql.jdbc.Driver
# resources/SqlMapConfig.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>
<!--配置mybatis环境-->
<properties resource="db.properties"></properties>
<!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
<typeAliases>
<package name="com.sn511.mybatis.domain"></package>
</typeAliases>
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC" />
<!--配置数据源-->
<dataSource type="POOLED">
<property name="driver" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</dataSource>
</environment>
</environments>
<!--mybatis映射配置的位置-->
<mappers>
<mapper resource="com/sn511/mybatis/dao/IUserDao.xml" />
</mappers>
</configuration>
# resources/com/sn511/mybatis/dao/IUserDao.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.sn511.mybatis.dao.IUserDao">
<!--查询-->
<!--
根据id查询用户信息
resultType: 用于指定结果集的类型
parameterType: 用于指定传入参数的类型
#{}: 它代表占位符,自动进行 java 类型和 jdbc 类型转换, 可以有效防止 sql 注入,可以接收简单类型值或 pojo 属性值
${}: 表示拼接sql串, 且不进行 jdbc 类型转换,可以接收简单类型值或 pojo 属性值
-->
<select id="findById" parameterType="int" resultType="com.sn511.mybatis.domain.User">
select * from user where id = #{id}
</select>
<select id="findUsersByName" parameterType="java.lang.String" resultType="com.sn511.mybatis.domain.User">
select * from user where name like '%${name}%'
</select>
<select id="findAll" resultType="com.sn511.mybatis.domain.User">
select * from user
</select>
<!--保存-->
<!--
parameterType: 参数类型,参数是一个类的对象,所以需要写全名称
ognl表达式: 完整写法应该是#{user.name}, user可以省略,会先找到user对象,然后在user对象中找到name属性
-->
<insert id="saveUser" parameterType="com.sn511.mybatis.domain.User">
insert into user(name, age) values (#{name}, #{age})
</insert>
<insert id="saveUserGetId" parameterType="com.sn511.mybatis.domain.User">
<!--获取保存记录的id-->
<selectKey keyColumn="id" keyProperty="id" resultType="int">
select last_insert_id();
</selectKey>
insert into user(name, age) values (#{name}, #{age})
</insert>
<!--更新-->
<update id="updateUser" parameterType="com.sn511.mybatis.domain.User">
update user set name = #{name}, age = #{age} where id = #{id}
</update>
<!--删除-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{id}
</delete>
</mapper>
- User.class
public class User {
private Integer id;
private String name;
private Integer age;
省略getter、setter方法
}
- IUserDao
public interface IUserDao {
/**
* 查询所有用户
* @return
*/
List<User> findAll();
/**
* 根据id查询用户
* @param id
* @return
*/
User findById(Integer id);
/**
* 根据姓名查询用户信息(模糊查询)
* @param name
* @return
*/
List<User> findUsersByName(String name);
/**
* 保存用户
* @param user
* @return 影响数据库记录的行数
*/
int saveUser(User user);
/**
* 保存用户并返回ID
* @param user
* @return
*/
int saveUserGetId(User user);
/**
* 更新用户
* @param user
* @return 返回影响记录的条数
*/
int updateUser(User user);
/**
* 删除用户
* @param id
* @return
*/
int deleteUser(Integer id);
}
- 测试
public class TestUser {
InputStream in;
SqlSessionFactoryBuilder builder;
SqlSessionFactory factory;
SqlSession sqlSession;
@Before
public void init() throws Exception{
//读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//构建者
builder = new SqlSessionFactoryBuilder();
//SqlSession工厂
factory = builder.build(in);
sqlSession = factory.openSession();
}
@After
public void destroy() throws Exception{
sqlSession.commit();
sqlSession.close();
in.close();
}
@Test
public void testFindAll(){
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
List<User> all = mapper.findAll();
System.out.println(all);
}
@Test
public void testFindUserById(){
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
User user = mapper.findById(1);
System.out.println(user.toString());
}
@Test
public void testFindUsersByName(){
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
List<User> all = mapper.findUsersByName("五");
System.out.println(all.toString());
}
@Test
public void testSaveUser(){
User user = new User();
user.setName("王二");
user.setAge(11);
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
int i = mapper.saveUser(user);
System.out.println(i);
}
@Test
public void testSaveUserGetId(){
User user = new User();
user.setName("麻子");
user.setAge(12);
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
int i = mapper.saveUserGetId(user);
System.out.println(i);
System.out.println(user.getId()); //主键id
}
@Test
public void testUpdateUser(){
User user = new User();
user.setId(5);
user.setName("赵六");
user.setAge(13);
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
int i = mapper.updateUser(user);
System.out.println(i);
}
@Test
public void testDeleteUser(){
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
int i = mapper.deleteUser(5);
System.out.println(i);
}
}
- 对参数和结果进行封装
public class QueryVo implements Serializable {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
public interface IUserDao {
List<User> findByQueryVo(QueryVo vo);
}
<?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.sn511.mybatis.dao.IUserDao">
<!--
id: 主键
result: 非主键
column: 数据表列名
property: 实体类属性名
-->
<resultMap id="userMap" type="com.sn511.mybatis.domain.User">
<!--主键-->
<id property="id" column="id"></id>
<!--非主键-->
<result property="name" column="name"></result>
<result property="age" column="age"></result>
</resultMap>
<select id="findByQueryVo" resultMap="userMap"
parameterType="com.sn511.mybatis.domain.QueryVo">
select * from user where name like #{user.name}
</select>
</mapper>
@Test
public void testFindByQueryVo(){
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
QueryVo vo = new QueryVo();
User user = new User();
user.setName("%王%");
vo.setUser(user);
List<User> users = mapper.findByQueryVo(vo);
System.out.println(users);
}
网友评论