mybatis与hibernate区别
hibernate是一个标准的orm框架(对象关系映射)不需要写sql语言。
但是如果需要对sql语句进行优化,比较困难
应用场景:适用于需求变化不多的小中型项目,比如后台管理系统
mybatis:专注于sql本身,需要程序员自己编写sql语句,优化比较方便
应用场景:需求变化较多的,互联网项目
mybatis开发dao方法
sqlsession使用范围
通过fatory创建sqlsession
工厂通过builder进行创建
使用单例模式管理sqlsessionFactory(工行内模式
将来使用spring与mybatis整合之后,使用单例模式管理sqlsessionFactory
sqlsession是一个面向用户的接口你
用于操作数据库的方法 selectOne selecttList
sqlsession是不安全的
还有数据域属性
原始开发dao方法
程序员需要写dao接口和实现类
需要向dao实现类中注入sqlsessionfatory,在方法体内通过sqlsessionfatory创建sqlsession
dao接口
public interface UserDao {
//根据id查询用户信息
public User findUserById(int id) throws Exception;
//添加用户信息
public void insertUser (User user) throws Exception;
//删除用户信息
public void deleteUser(int id )throws Exception;
}
实现接口类
package cn.mmz.mybatis.dao;
import cn.mmz.mybatis.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
/**
* @Classname UserDaoImpl
* @Description dao接口实现类
* @Date 2020/1/3 20:43
* @Created by mmz
*/
public class UserDaoImpl implements UserDao {
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById",id);
sqlSession.close();
return user;
}
@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.insertUser",user);
sqlSession.commit();
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("test.deleteUser",id);
sqlSession.commit();
sqlSession.close();
}
}
如何创建一个测试类,
cmd+shift+T 在想要测试的类按下,就可以生成一个测试类了
package cn.mmz.mybatis.dao;
import cn.mmz.mybatis.pojo.User;
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 java.io.InputStream;
/**
* @Classname UserDaoImplTest
* @Description TODO
* @Date 2020/1/3 21:04
* @Created by mmz
*/
public class UserDaoImplTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception{
//创建sqlsessionFactory
String resource = "SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂,传入配置文件信息
sqlSessionFactory =new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void findUserById() throws Exception{
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
User user = userDao.findUserById(1);
System.out.println(userDao);
}
@Test
public void insertUser() {
}
@Test
public void deleteUser() {
}
}
以上是生成的测试类,@Before写的是在进行单元之前都需要做些什么
就是需要生成sqlSessionFactory
然后在@Test方法中测试用例
就可以了
public void findUserById() throws Exception{
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
User user = userDao.findUserById(1);
System.out.println(userDao);
}
总计原始dao开发问题
dao接口实现类方法存在大量的模板代码, 设想能否把代码提取出来
调用sqlsession方法时,将statement硬编码了
调用sqlsession方法传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错。不利于程序员开发
mapper代理方法
程序员只需要写接口,
还需要编写mapper映射文件
需要遵循开发规范
开发规范
namespace 等于mapper接口地址
mapper.java接口中的方法名和mapper.xml中的statement的id一致
mapper接口中的方法输入参数类型和statement的parameter指定的类型一致
mapper.java返回值与映射文件statement中的resultType的类型一致
总结
以上开发规范主要是对下边的代码进行统一生成
mybatis可以自动生成mapper接口实现类的代理对象
测试
我们一开始基于原始dao开发的时候,先创建了一个Userdao的接口interface,然后实例化这个接口为UserDaoImpl,这里面的方法写了如何进行操作
@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById",id);
sqlSession.close();
return user;
}
所以当我们用mapper接口开发的时候,我们没有这个UserDaoImpl实例类,所以我们一开始要创建这个会话
SqlSession sqlSession = sqlSessionFactory.openSession();
然后在创建该UserMapper的对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
这句话mybatis自动生成mapper代理对象
测试的时候报错了,原因是你配置好了UserMapper文件,你还需要把这个文件配置总体的SqlMapperConfig文件中
结果成功,由于User没加toString方法,所以返回的应该是地址
那么加上toString方法之后
代理对象内部调用selectOne 或者是selectList
如果mapper方法返回非集合对象,单个pojo对象,代理对象内部通过selectOne进行查询对象
那么如果是一个集合对象,那么会返回一个List
public void findUserByName() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> user = userMapper.findUserByName("小明");
System.out.println(user);
}
问题所在
mapper接口的方法参数只有一个,是否影响系统开发?
系统框架中,dao层代码是公用的。
即使mapper接口只有一个参数,可以使用包装类型的pojo来满足不同的业务方法的需求
注意:持久层中方法可以用包装类型,service方法中不建议使用包装类型(不利于业务层的可拓展维护)