Mybatis开发DAO层的两种方法
Mybatis开发DAO方法
常用类
SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder创建会话工厂
将SqlSessionFactoryBuilder当成一个工具类使用,不需要使用单例管理SqlSessionFactoryBuilder。
在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。
SqlSessionFactory
通过SqlSessionFactory创建SQLSession,使用单例模式管理SqlSessionFactory(工厂一旦创建,使用一个实例,整个项目只有一个实例)
将来mybatis和Spring整合后,使用单例模式去管理SqlSessionFactory。
SqlSession
SqlSession是一个面向用户(程序员)接口
SqlSession提供了很多操作数据库的方法,
selectOne:返回单个对象,根据主键来查询
selectList:返回1个或者多个对象。
SqlSession是线程不安全,在SqlSession实现类中除了有接口中方法(操作数据库的方法),还有数据域属性。
SqlSession最佳应用场合是在方法体内,定义成局部变量使用。
使用Mybatis开发DAO层
方法一:最基本的方法
目录结构如下:
实现一个案例,从一个User表中根据id查找一个用户
UserDao为一个接口,UserDaoImpl为该接口的实现类
UserDao
public interface UserDao {
/**
* 得到用户通过id
* @param id
* @return
*/
public User getUserById(Integer id);
}
UserDaoImpl
public class UserDaoImpl implements UserDao {
//在创建DAO的时候,需要传递工厂
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User getUserById(Integer id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
User ser = sqlSession.selectOne("user.findUserById",id);
return ser;
}
}
POJO为数据库中表的实体类的映射
package com.hyx2.dao_first.pojo;
import java.util.Date;
public class User {
private Integer id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public User() {
}
public User(String username, String sex, Date birthday, String address) {
this.username = username;
this.sex = sex;
this.birthday = birthday;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" + "id=" + id + ", username='" + username + '\'' + ", sex='" + sex + '\'' + ", birthday=" + birthday + ", address='" + address + '\'' + '}';
}
}
配置User.xml文件,执行sql查询语句
<?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="user">
<select id="findUserById" parameterType="int" resultType="pojo.User">
select * from user where id = #{id}
</select>
</mapper>
接下来为配置好的Mybatis配置文件注册该User.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>
<!--数据库配置信息-->
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!--数据库连接要素,数据库,数据库位置,账户,密码-->
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!--配置实体类的xml文件,在这文件中执行sql语句-->
<mappers>
<mapper resource="User.xml"></mapper>
</mappers>
</configuration>
数据库连接配置信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis01?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123
执行测试
import UserDao;
import impl.UserDaoImpl;
import 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.IOException;
import java.io.InputStream;
public class Demo01 {
private SqlSessionFactory sqlSessionFactory;
@Before
public void fun0() throws IOException {
InputStream inputStream = Resources.getResourceAsStream( "hyx2_first_sqlMapconfig.xml" );
//通过配置创建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build( inputStream );
}
@Test
public void fun(){
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
User userById = userDao.getUserById(1);
System.out.println(userById);
}
}
存在的问题
(1)dao接口实现类方法中,存在大量模板代码(重复),设想能否将这项代码抽取出来,大大减少程序员的工作量。
AOP思想;代理模式
(2)调用SQLSession方法的时候,传入的变量类型Object,即使变量类型传入错误,在编译阶段也不报错,不利于程序的开发。
方法二:Mapper代理开发方法(只需要写Mapper接口(相当于DAO接口))
使用该方法,程序员要干的事情
程序员只需要编写Mapper接口(就相当于DAO),mybatis可以自动生成Mapper接口实现类对象。但是:要像自动生成实现类对象,需要遵循一些规范。
(1)Mapper接口和Mapper.xml放在同一个目录下。同名。
(2)Mapper.xml中namespace的值等于Mapper接口的全路径
(3)statementId,parameterType、ResultType和接口名字、入参类型、返回值类型要一致。
使用该方法代码实现方法一中的案例:
目录结构如下:
User直接使用方法一种的代码
UserMapper为一个接口:
package mapper;
import pojo.User;
public interface UserMapper {
/**
* 找到用户通过id
*/
public User findUserById(Integer id);
}
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.hyx2.dao_two.mapper.UserMapper">
<select id="findUserById" parameterType="int" resultType="pojo.User">
select * from user where id = #{id}
</select>
</mapper>
hyx2_two_sqlMapconfig.xml中内容与案例一种的一样,只需要修改mappers中的代码
<!--配置实体类的xml文件,在这文件中执行sql语句-->
<mappers>
<mapper resource="com/hyx2/dao_two/mapper/UserMapper.xml"></mapper>
</mappers>
开始测试:
package test;
import mapper.UserMapper;
import pojo.User;
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 java.io.IOException;
import java.io.InputStream;
public class Dmo01 {
private SqlSessionFactory sqlSessionFactory;
@Before
public void fun0() throws IOException {
InputStream inputStream = Resources.getResourceAsStream( "hyx2_two_sqlMapconfig.xml" );
//通过配置创建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build( inputStream );
}
@Test
public void fun(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.findUserById(1);
System.out.println(userById);
}
}
使用Mapper开发常见问题
下图的对应关系一定要注意
代理内部selectOne和selectList怎么区别的
根据接口的返回值来区别的。
如果返回值是POJO对象,selectOne来实现。
如果返回值是结合对象,selectList来实现。
Mapper接口方法只能是一个参数
系统是否不利于扩展维护。
系统框架中,DAO层的代码是被业务层公用的
即使Mapper接口只有一个参数,可以使用包装类型的POJO满足不同业务方法的需求。