Mybatis开发Dao的方式
MyBatis开发Dao有两种方式:原始Dao的开发方式,Mapper动态代理的方式。
两种开发方式在企业开发中均有运用。都要掌握。
使用myBatis时,需要对其进行一个全局的管理配置。
sqlMappingConfig.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>
<!-- 全局参数配置,在需要时候进行配置 -->
<!-- <settings></settings> -->
<!-- 别名设置 -->
<!-- 单个配置
type:类型路径
alias:别名-->
<!-- <typeAliases>
<typeAlias type="cn.edu.hpu.ssm.po.User" alias="user"/>
</typeAliases> -->
<!-- 批量设置(推荐使用)
指定包名,mybatis自动扫描扫描po类,自动定义别名。默认为类名(首字母大写或小写) -->
<typeAliases>
<package name="cn.edu.hpu.ssm.po"/>
</typeAliases>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事物控制有mybatis控制-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 配置mpper,加载映射文件 -->
<!-- <mappers>
<mapper resource="sqlmap/User.xml"/>
<mapper resource="mapper/UserMapper.xml"/>
</mappers> -->
<!-- 通过mapper接口,加载映射文件
规范:mapper接口名必须与mapper。xml文件名相同,且放在同一包下
前提是使用mapper代理的方式 -->
<mappers>
<mapper class="cn.edu.hpu.ssm.mapper.UserMapper"/>
<mapper class="cn.edu.hpu.ssm.mapper.OrdersMapperCustom"/>
</mappers>
</configuration>
其中关于数据库的一些配置,抽取出来了,这样可以减少硬编码:
db.properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456
1.原始Dao的开发方式
原始Dao的开发,需要程序员自己编写Dao的接口和Dao接口的实现类。(一下以一个按照id查询为例说明)
1.映射文件:
<?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">
<!-- namespace:命名空间,作用就是对sql进行分类化管理,sql隔离
注意:在使用mapper的代理方法开发时,有重要作用 -->
<mapper namespace="test">
<!-- 在映射文件中配置多个,sql语句 -->
<!-- 按照id查询 -->
<!-- 将sql语句封装到MapperStatement中,所以也将id 成为statement的Id -->
<!-- paramerType:指定输入参数的类型。
#{ } :代表占位符。
#{id }:表示接受输入参数id的值,如果输入参数是简单类型,#{ }中的参数名可以任意
,可以是value或是其他值
resultType:表示sql输出结果的所映射的Javabean的对象类型,resultType指定将单条记录映射成Java对像-->
<select id="findUserById" parameterType="int" resultType="cn.edu.hpu.ssm.po.User">
SELECT * FROM USER WHERE id = #{value}
</select>
</mapper>
2.Dao接口:
Public interface UserDao {
public User getUserById(int id) throws Exception;
}
3.Dao接口的实现
Public class UserDaoImpl implements UserDao {
//通过构造函数注入SqlSessionFactory
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
this.setSqlSessionFactory(sqlSessionFactory);
}
private SqlSessionFactory sqlSessionFactory;
@Override
public User getUserById(int id) throws Exception {
SqlSession session = sqlSessionFactory.openSession();
User user = null;
try {
//通过sqlsession调用selectOne方法获取一条结果集
//参数1:指定定义的statement的id,参数2:指定向statement中传递的参数
user = session.selectOne("test.findUserById", 1);
System.out.println(user);
} finally{
session.close();
}
return user;
}
}
通过上面的例子,我们可以总结:
原始Dao开发存在以下问题:
Dao的方法存在重复代码,:通过sqlSessionFactory创建SqlSession,调用sqlSession数据库的操作方法。
调用sqlSession操作数据库的方法(第一个参数)时,硬编码,不利于系统的维护。
SqlSessionFactory的使用范围:
通过SQLSessionFactoryBuilder创建会话工厂SQLSessionFactory。将SQLSessionFactoryBuilder当做一个工具类来使用即可,不需要使用单例模式去管理。
通过SQLSessionFactory创建sqlSession,使用单例模式管理SQLSessionFactory,(工厂一旦被创建,使用一个实例)。将来mybatis与spring整合后,使用单例模式来管理sqlSessionFactory。
sqlSession是线程不安全的,在sqlsession中不但存在操作数据库的方法,还有数据域属性。sqlSession最佳应用场合,是在方法体内,定义成局部变量使用。
2.Mapper代理的方式:
mapper动态代理实现的原理:
mapper接口开发方式,只需要程序员编写mapper接口(相当于Dao接口),有mybatis框架根据接口定义创建接口的动态代理对象,代理的方法体与上面Dao实现类中的方法体相类似
Mapper接口开发要符合一下规范:
1.Mapper.xml中namespace路径与mapper接口路径相同
2.mapper接口中的方法名,与Mapper.xml中对应statement的id相同
3.mapper接口中方法的输入参数类型和mapper.xml中定义的对应sql的ParameterType的类型相同
4.mapper接口中方法的返回值类型和mapper.xml中定义的对应sql的ResultType的类型相同
1.Mapper.xml写法:(与上面User.xml不同的是namespace做了定义)
<?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">
<!-- namespace:命名空间,作用就是对sql进行分类化管理,sql隔离
注意:在使用mapper的代理方法开发时,有重要作用
namespace命名必须与Mapper接口的路径相同 -->
<mapper namespace="cn.edu.hpu.ssm.mapper.UserMapper">
<!-- 按照id查询 -->
<!-- 将sql语句封装到MapperStatement中,所以也将id 成为statement的Id -->
<!-- paramerType:指定输入参数的类型。
#{ } :代表占位符。
#{id }:表示接受输入参数id的值,如果输入参数是简单类型,#{ }中的参数名可以任意
,可以是value或是其他值
resultType:表示sql输出结果的所映射的Javabean的对象类型,resultType指定将单条记录映射成Java对像-->
<select id="findUserById" parameterType="int" resultType="User">
SELECT * FROM USER WHERE id = #{value}
</select>
</mapper>
2.mapper.java(接口文件)
package cn.edu.hpu.ssm.mapper;
import java.util.List;
import java.util.Map;
import cn.edu.hpu.ssm.po.User;
import cn.edu.hpu.ssm.po.UserCustom;
import cn.edu.hpu.ssm.po.UserQueryVo;
public interface UserMapper {
//返回值类型必须与mapper.xml中resultType类型相同
//形参必须与mapper.xml中的parameterType类型相同
//mapper.java接口中的方法名和mapper.xml中statement的id一致
public User findUserById(int id) throws Exception;
}
3.测试文件:(通过junit)
public class MapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
String resource = "SqlMapConfig.xml";
InputStream input = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
}
/**
* 通过id查询
* @throws Exception
*/
@Test
public void testFindUserById() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
//通过session自动创建mapper代理对象
UserMapper userMap = session.getMapper(UserMapper.class);
User user = userMap.findUserById(1);
System.out.println(user);
}
}
4.对Mapper动态代理的一个小结:
1.使用mapper代理时,输入参数类型可以使用pojo的包装对象,或是mapper对象,保证dao的同性。
2.selectOne和selectList
动态代理对象通过sqlsession.selectOne和sqlsession.selectList,是通过对返回值类型进行判断而选择调用哪一个方法。如果返回单个对象则调用selectOne,返回集合对象则调用selectList