一、mybatis 和 hibernate 的区别和应用场景
hibernate:是一个标准的 ORM 框架(对象关系映射)。入门门槛较高的,不需要写 sql,sql 语句自动生成了。对 sql 语句进行优化、修改比较困难的。
应用场景:使用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa
mybatis:专注是 sql 本身,需要程序员写 sql,修改优化比较方便。也可以实现映射。
应用场景:使用需求变化较多的项目,比如:互联网项目,
二、实现 dao 的编写(以 user 为例)
1、编写 userDAO
- package dao;
- import entity.users;
- public interface UserDao {
- publicusers findUserByid(intid)throws Exception;
- public voidinsertUser(users user)throws Exception;
- public voidupdateUser(users user)throws Exception;
- public voiddeleteUser(users user)throws Exception;
- }
2、编写 userDaoImpl
因为现在没有和 spring 整合,所以 SqlSessionFactory 当工具类使用,用构造函数的方式注入,以后会交给 spring 管理
- package dao;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import entity.users;
- public classUserDaoImplimplements UserDao {
- privateSqlSessionFactory sqlSessionFactory=null;
- public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
- this.sqlSessionFactory=sqlSessionFactory;
- }
- @Override
- publicusers findUserByid(intid)throws Exception {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- users u=sqlSession.selectOne("test.srarchByid", id);
- System.out.println(u.getBirthday().toString());
- sqlSession.close();
- return u;
- }
- @Override
- public voidinsertUser(users user)throws Exception {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- sqlSession.insert("test.insertUser", user);
- System.out.println(user.getId());
- sqlSession.commit();
- sqlSession.close();
- }
- @Override
- public voidupdateUser(users user)throws Exception {
- // TODO Auto-generated method stubSqlSession sqlSession=sqlSessionFactory.openSession();
- sqlSession.update("updateUser",user);
- System.out.println(user.getId());
- sqlSession.commit();
- sqlSession.close();
- }
- @Override
- public voiddeleteUser(users user)throws Exception {
- // TODO Auto-generated method stubSqlSession sqlSession=sqlSessionFactory.openSession();
- sqlSession.delete("test.deleteUser",3);
- sqlSession.commit();
- sqlSession.close();
- }
- }
3、测试类
这里只测试了根据 ID 查询和插入,其他的类型,在这里不一一测试了。
- package dao;
- import java.io.InputStream;
- import java.util.Date;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.apache.ibatis.session.SqlSessionFactoryBuilder;
- import org.junit.Before;
- import org.junit.Test;
- import entity.users;
- public class UserDaoImplTest {
- private SqlSessionFactory sqlSessionFactory;
- @Before
- public voidsetUpBeforeClass()throws Exception {
- String resource="SqlMapConfig.xml";
- InputStream stream=Resources.getResourceAsStream(resource);
- sqlSessionFactory=new SqlSessionFactoryBuilder().build(stream);
- }
- @Test
- public voidtestFindUserByid()throws Exception {
- UserDao userDao=new UserDaoImpl(sqlSessionFactory);
- users u=userDao.findUserByid(1);
- System.out.println(u.getName());
- }
- @Test
- public voidtestInsertUser()throws Exception {
- users user=new users();
- user.setName("王五");
- user.setSex("f");
- user.setAddress("五道口");
- user.setBirthday(new Date());
- UserDao userDao=new UserDaoImpl(sqlSessionFactory);
- userDao.insertUser(user);
- }
- }
三、原始 DAO 开发问题
1.DAO 的接口实现类方法中存在大量的模板方法。
2、调用 SQLSession 方法时将 statement 硬编码了。
3、调用 SQLSession 方法时传入的变量,由于 sqlsession 方法使用泛型,即使参数类型错误,编译阶段不报错。
由于以上的问题,mybatis 提出了 mapper 代理的概念。这个概念的提出有效的解决了以上提出的问题,程序员只需要开发 mapper 代理(类似于 dao 的接口),框架自动为其生成实现类。下面将详细介绍 mapper 的开发步骤。
四、mapper 代理的开发(同样以 user 为例)
1、开发规范:
1)在 mapper.xml namespace 等于 mapper 接口地址
2)mapper.java 接口的方法名与 mapper.xml 的 statement 中得 id 一致
3)mapper.java 接口中得方法输入参数和 mapper.xml 中得 statement 的 parameter 指定的类型一致。
4)接口返回值类型与 statement 中 resultType 类型一致。
2、代码实现
1)编写 userMapper.xml 映射文件
- select * from users where id = # {
- id
- }
- select * from users where name like '%${value}%'
- insert into users(name, birthday, address, sex) values(# {
- name
- },
- # {
- birthday
- },
- # {
- address
- },
- # {
- sex
- })
- select last_insert_id()
- delete from users where id = # {
- id
- }
- update users set name = # {
- name
- },
- address = # {
- address
- },
- birthday = # {
- birthday
- },
- sex = # {
- sex
- }
- where id = # {
- id
- }
在上一篇博文中我们开发了 user.xml,这个是在开发普通 dao 时使用的配置文件,这里的 userMapper 与其功能类似。但需要注意的是 namespace 要与 mapper 接口的全名地址一样,mapper 的 ID 要与 mapper 代理中得接口方法名相同。
2)mapper 代理接口
- package mapper;
- import java.util.List;
- import entity.users;
- public interface UserMapper {
- publicusers findUserByid(intid)throws Exception;
- publicList findUserByName(String name) throws Exception;
- public voidinsertUser(users user)throws Exception;
- public voidupdateUser(users user)throws Exception;
- public voiddeleteUser(intid)throws Exception;
- }
3)测试代码
- package mapper;
- import static org.junit.Assert.fail;
- import java.io.InputStream;
- import java.util.Date;
- 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.Before;
- import org.junit.Test;
- import entity.users;
- public class UserMapperTest {
- private SqlSessionFactory sqlSessionFactory;
- @Before
- public voidsetUp()throws Exception {
- String resource="SqlMapConfig.xml";
- InputStream stream=Resources.getResourceAsStream(resource);
- sqlSessionFactory=new SqlSessionFactoryBuilder().build(stream);
- }
- @Test
- public voidtestFindUserByid()throws Exception {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
- users user=userMapper.findUserByid(5);
- System.out.println(user.getName());
- }
- @Test
- public voidtestFindUserByName()throws Exception {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
- List list=userMapper.findUserByName("王");
- for(users u:list){
- System.out.println(u.getName());
- }
- }
- @Test
- public voidtestInsertUser()throws Exception {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
- users user=new users();
- user.setName("Danny");
- user.setAddress("America");
- user.setBirthday(new Date());
- user.setSex("f");
- userMapper.insertUser(user);
- sqlSession.commit();
- sqlSession.close();
- System.out.println(user.getId());
- }
- @Test
- public voidtestUpdateUser()throws Exception {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
- users user=new users();
- user.setId(19);
- user.setName("Danny");
- user.setAddress("America");
- user.setBirthday(new Date());
- user.setSex("m");
- userMapper.updateUser(user);
- sqlSession.commit();
- sqlSession.close();
- System.out.println(user.getId());
- }
- @Test
- public voidtestDeleteUser()throws Exception {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
- userMapper.deleteUser(19);
- sqlSession.commit();
- sqlSession.close();
- }
- }
mapper 开发步骤总结为一下三个步骤:
1)程序员还需要编写 mapper.xml 映射文件
2)编写 mapper 接口
3)mybatis 自动生成 mapper 接口的实现类对象
五、SQLMapConfig 中得其他配置内容
1.properties
需求:将数据库的连接参数单独配置在 db.properties 中,只需要在 Sqlmapconfig.xml 中加载 db.properties 的属性值,不需要再 Sqlmapconfig.xml 中硬编码了
操作:
新建一个 db.properties,内容如下:
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/mybatisTest?characterEncoding=utf-8jdbc.username=root
- jdbc.password=123456
然后在 Sqlmapconfig.xml 中加入以下标签
<properties resource="db.properties"> </properties> ,这个标签要被 <configuration> 包住。同时可以在 properties 中再配置 property,实现新的属性值,它会覆盖 resource 中得同名属性
通过以上步骤就实现了数据库连接字符串的非硬编码实现。
注意!Mybatis 将按照下面的顺序来加载属性:
在 properties 元素体内定义的属性首先被读取
然后会读取 properties 元素中 resource 或 url 加载的属性,它会覆盖已读取得同名属性
在最后读取 parameterType 传递的属性,它会覆盖已读取得同名属性。
2.setting 全局的参数配置
用来调整一些运行参数,例如二级缓存和延迟加载。
3.typeAliaes
在 mapper.xml 中,定义很多的 statement,statement 需要 parameterType 和 rusultType 指定参数的类型,
但是指定的类型要求是全路径的,不方便开发,就可以针对这些个全路径名字定义别名来实现。
操作:
(1)针对单个别名定义
在 Sqlmapconfig.xml 中添加以下内容
- <typeAliases>
- <typeAlias type="entity.users" alias="user"/>
- </typeAliases>
然后在 userMapper.xml 中就可以用 user 代替 entity.users
(2)可以直接对整个 package 做别名定义,指定报名后,将自动扫描包中得类自动定义别名,别名为类名,首字母可大写也可小写。
4.mapper
这个标签除了使用上面的 resource 属性外,还可以使用 class,通过 mapper 接口加载映射文件
需要遵循一些规范:需要 mapper 的类名和 mapper.xml 的名字一样且在一个目录下。
同样 class 属性支持 package 批量加载。
来源: http://www.cnblogs.com/softzrp/p/7096185.html