下面来继续讨论mybatis开发Dao的方法
我们前面使用原始的Dao开发方法,发现了许多弊端,我们下面使用mapper代理来写Dao方法。
1.mapper代理方法(程序员只需要mapper接口(相当 于dao接口))
开发人员需要先编写Mapper接口(相当 于dao接口),需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。
package cn.edu.hpu.mybatis.mapper;
import cn.edu.hpu.mybatis.PO.User;
//用户管理的Dao接口
public interface UserMapper {
//根据Id查询用户信息
public User findUserById(int id) throws Exception;
//添加用户信息
public void insertUser(User user) throws Exception;
//删除用户信息
public void deleteUser(int id) throws Exception;
//修改用户信息
public void updateUser(User user) throws Exception;
//根据姓名查找用户
public List findUserByUserName(String username) throws Exception;
}
开发人员还要编写mapper.xml映射文件
我们在src同文件夹下的config文件夹下创建mapper包,在包下创建UserMapper.xml文件,内容同之前写过的User.xml文件一样。
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
SELECT LAST_INSERT_ID()
insert into user(username,birthday,sex,address) value(#{username},#{birthday,jdbcType=DATE},#{sex},#{address})
delete from user where id=#{id}
update user set username=#{username},birthday=#{birthday,jdbcType=DATE},sex=#{sex},address=#{address}
where id=#{id}
别忘记在SqlMapConfig.xml中加载映射文件
开发规范:
A、在mapper.xml中namespace等于mapper接口地址
!– namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用,就是对应的mapper接口地址 –>
……
B、mapper.java接口中的方法名和mapper.xml中statement的id一致
public findUserById()
对应
C、mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。
public findUserById(int id)
对应
D、mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。
public User findUserById(int id)
对应
遵循这些开发规范,mybatis可以自动生成mapper接口实现类代理对象。
总结:
以上开发规范主要是对下边的代码进行统一生成:
User user=sqlSession.selectOne("test.findUserById",id);
sqlSession.insert("test.insertUser",user);
mapper.java与mapper.xml互联互助
接下来我们直接根据接口来测试:
package cn.edu.hpu.mybatis.test;
import java.io.InputStream;
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 cn.edu.hpu.mybatis.PO.User;
import cn.edu.hpu.mybatis.mapper.UserMapper;
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
//注解Before是在执行本类所有测试方法之前先调用这个方法
@Before
public void setup() throws Exception{
//创建SqlSessionFactory
String resource="SqlMapConfig.xml";
//将配置文件加载成流
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂,传入mybatis配置文件的信息
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception{
SqlSession sqlSession=sqlSessionFactory.openSession();
//创建UserMapper代理对象
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
//调用userMapper的方法
User user=userMapper.findUserById(1);
System.out.println(user.getUsername());
}
}
测试testFindUserById()方法,结果:张三
输出日志信息:
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 14069849.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@d6b059]
DEBUG [main] - ==> Preparing: SELECT * FROM USER WHERE id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] -
这里我们使用mapper代理的方法,不需要方法的实现体就完成了查找方法,是不是很轻松?
其他增删改写的方法与上面差不多,但是,当我们实现利用姓名模糊查询的时候,返回的是List集合的数据,我们要注意:
2.一些问题总结
2.1代理对象内部调用selectOne或selectList
如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。
如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。
这些是MyBatis内部自动执行的,是不是很方便?我们可以测试一下是不是这样:
测试方法:
@Test
public void testFindUserByUserName() throws Exception{
SqlSession sqlSession=sqlSessionFactory.openSession();
//创建UserMapper代理对象
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
//调用userMapper的方法
List users=userMapper.findUserByName("张三");
for (int i = 0; i User user=(User)users.get(i);
System.out.println(user.getId()+":"+user.getUsername());
}
}
测试结果:
1:张三
4:张三丰
输出日志:
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1668655.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@19762f]
DEBUG [main] - ==> Preparing: select * from user where username like '%张三%'
DEBUG [main] - ==> Parameters:
DEBUG [main] -
测试成功,说明MyBatis内部确实是这么做的
我们发现,mapper接口中的参数好像只有一个,Mybatis内部好像也只能自动处理一个参数的mapper方法,那么mapper接口方法参数只能有一个是否影响系统开发?
问:mapper接口方法参数只能有一个,系统是否不利于扩展维护。
答:
系统 框架中,dao层的代码是被业务层公用的。
即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。
注意:持久层方法的参数可以包装类型、map。。。,service方法中建议不要使用包装类型(不利于业务层的可扩展)。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net