目录
①:JavaBean传递模式(传递的参数为JavaBean的实体类)
②:Map模式(如果传递的参数个数较少而且没有对应的JavaBean)
一、原始dao开发的问题
程序员需要写dao接口和dao实现类,需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession
举例:1.先创建一个dao接口里面定义了一些方法
其中的Users是Java对象对应着数据库表
public interface UserDao {
//根据id查询用户信息
public Users findUserById(int id);
//添加用户信息
public void insertUser(Users user);
//根据id删除用户信息
public void deleteUser(int id);
}
2.dao接口实现类
public class UserDaoImpl implements UserDao {
// 需要向dao实现类中注入SqlSessionFactory
// 这里通过构造方法注入
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();
}
}
测试代码
从上面的代码可以看出:1.dao接口实现类方法中存在大量模板方法
2.调用sqlsession方法时将statement的id硬编码了
3.调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
二、mapper动态代理模式
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
开发规范:
1、在mapper.xml中namespace等于mapper接口地址的全路径
<!--
namaspace等于接口的全路径
-->
<mapper namespace="com.mybatis.UserDao">
</mapper>
2、mapper.java接口中的方法名和mapper.xml中statement的id一致
statement的id就是下图红框:
举例:比如UserDao接口中的findUserById方法,则对应于mapper.xml中的statement的id要与该方法名一致
3、mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。
举例:比如UserDao接口中的findUserById方法,输入参数为int类型
则对应mapper.xml中的输入参数类型也为int
4、mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。
举例:比如UserDao接口中的findUserById方法,输出类型为Users对象
则对应的statement的resultType类型也要为该对象(resultType="该对象的全路径")
三、测试
下面的代码是采用动态代理模式,调用了UserDao接口的findUserById方法
其中session.getMapper(UserDao.class)是用来生成动态代理对象,生成的对象其实就是UserDao接口,然后就可以直接调用该接口的方法进行操作,在调用接口后mybatis会自动的去与之对应的namespace里寻找对应statement的id然后执行sql语句。
@org.junit.Test
public void test() throws IOException {
String resource = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
UserDao mapper = session.getMapper(UserDao.class);
Users user = mapper.findUserById(1);
System.out.println(user);
}
可以看到由于没有了接口的实现类,大大的减少了代码数量
但这时有一问题,可以看到在mapper.xml的statement中输入参数parameterType只能有一个,但是实际业务使用时,用户想要多条件查询或多条件其他操作,但此时输入参数只能有一个怎么办?
四、Mybatis的多参数传递
mybatis框架的多参数传递有三种方式:JavaBean传递、Map、注解@param
①:JavaBean传递模式(传递的参数为JavaBean的实体类)
举例:此时想要通过id和nickname 去查询数据库中的用户信息
1.首先在接口中创建相应的方法
2.在对应的mapper.xml创建statement
3.进行代码测试
因为需要传递Users对象,并且要根据该对象的id、nickname进行查询,所以需要对该对象设置想要查询的id、nickname
@org.junit.Test
public void test() throws IOException {
String resource = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
UserDao mapper = session.getMapper(UserDao.class);
Users user = new Users();
user.setId(1);
user.setNickname("大王");
Users u = mapper.getUserByidAndNickname(user);
System.out.println(u);
}
②:Map模式(如果传递的参数个数较少而且没有对应的JavaBean)
举例:与JavaBean模式相同也是根据id、nickname进行多条件查询
1.首先在接口类中定义方法(传递的参数定义为Map)
2.在对应的mapper.xml创建statement
需注意:#{}中的id、nickname对应的是map中的key!
3.进行代码测试
Map中的key要与statement中sql语句#{}相对应。
③:注解@param模式
JavaBean模式需要创建对象,Map需要创建Map对象,不简洁。这时可以采用@param注解,它可以明确指定封装参数时map的key
举例:与JavaBean模式相同也是根据id、nickname进行多条件查询
1.首先在接口类中定义方法(注意参数)
public interface UserDao {
//通过id和nickname 去查询数据库中的用户信息
public Users getUserByidAndNickname(@Param("param1") int id, @Param("param2") String nickname);
}
2.在对应的mapper.xml创建statement
3.进行代码测试
直接调用接口方法传递参数即可。
其实@param注解方式也是使用Map不过mybatis框架底层为我们实现好了,过程如下图:
1.首先通过调用接口方法
2.然后会把输入到接口方法中的参数命名为param1、param2,再传递到statement的sql与剧中
3.最后sql语句中通过#{} 获取相应的参数内容进行sql语句
五、参数为集合或数组
public interface UserDao {
public List<Users> getUserByCollection(Collection list);
}
foreach标签:循环遍历集合,支持数组和List、Set接口,对其提供遍历功能
传递List类型的参数,collection="list";传递数组类型参数,collection="array".
item表示list中的每一个元素
separator:多条记录之间的分割符
select * from users where id in(id1,id2....); 所以open为(
close为)
测试代码
@org.junit.Test
public void test() throws IOException {
String resource = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
UserDao mapper = session.getMapper(UserDao.class);
int[] ids = {1,2,3,4,5};
List<Users> users = mapper.getUserByIds(ids);
System.out.println(users);
}