【SSM】MyBatis动态代理及参数传递

本文详细介绍了MyBatis的动态代理模式,如何避免原始DAO开发的问题,以及在多参数传递中JavaBean、Map和注解@param三种模式的使用方法,包括示例代码和测试。同时,讲解了参数为集合或数组时如何利用foreach标签处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、原始dao开发的问题

二、mapper动态代理模式

三、测试

四、Mybatis的多参数传递

①:JavaBean传递模式(传递的参数为JavaBean的实体类)

②:Map模式(如果传递的参数个数较少而且没有对应的JavaBean)

③:注解@param模式

五、参数为集合或数组


一、原始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);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值