Mybatis多参数及Map,实体对象传递方法案例 - 寒江孤影

Mybatis多参数及Map,实体对象传递方法案例

作者: 36D小可爱

全网最全的网络资源分享网站

手机扫码查看

标签:

MyBatis传参数

特别声明:文章多为网络转载,资源使用一般不提供任何帮助,特殊资源除外,如有侵权请联系!

前言

现在大多项目都是使用Mybatis了,但也有些公司使用Hibernate。使用Mybatis最大的特性就是sql需要自己写,而写sql就需要传递多个参数。面对各种复杂的业务场景,传递参数也是一种学问。

下面运行一个Java项目来演示多参数传递的方法。

方法1:顺序传参法

下面这个接口传入了2个参数分别是id和name

//接口
public interface UserMapper {
	public List<User> getAll(Integer id,String name);
}
接口的实现
public class Userlmpl implements UserMapper {
	private UserMapper userMapper;
	
	public Userlmpl() {
		userMapper=MyBatisUtil.getMapper(UserMapper.class);
	}

	@Override
	public List<User> getAll(Integer id, String name) {
		return userMapper.getAll(id, name);
	}
}
需要配置的xml
<mapper namespace="com.test.dao.UserMapper">
	<select id="getAll" resultType="user">
		select * from user where id=#{id} and name=#{name}
	</select>
</mapper>
测试
public class Test {
	public static void main(String[] args) {

		SqlSession session = null;
		session = MyBatisUtil.getSqlSession();
		UserMapper dao = new Userlmpl();
		int id=1;
		String name="小红";
		List<User> list = dao.getAll(id,name);
		for (User user : list) {
			System.out.println(user);
		}

	}
}
运行后发现报错
Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
那么这段报错是什么意思呢,意思是找不到参数“id”。可用参数为[arg1,arg0,param1,param2]
那么这个问题如何解决呢?
用到第一种方法顺序传参法
param1则是我们传进来的第一个参数param2是第二个
select * from user where id=#{param1} and name=#{param2}
#{}里面的数字代表你传入参数的顺序。  这种方法不建议使用,sql层表达不直观,且一旦顺序调整容易出错。

方法2:@Param注解传参法

需要把接口代码写成如下

public List<User> getAll(@Param("id") Integer id,@Param("name") String name);
#{}里面的名称对应的是注解 @Param括号里面修饰的名称。与方法1不同之处我们对参数做了别名,可以与传过来的参数名称相同非常的直观

方法3:Map传参法

需要把接口代码写成如下

public List<User> getAll(Map<String, Object> map);

接口实现类代码写成

public class Userlmpl implements UserMapper {
	private UserMapper userMapper;
	
	public Userlmpl() {
		userMapper=MyBatisUtil.getMapper(UserMapper.class);
	}
	
	@Override
	public List<User> getAll(Map<String, Object> map) {
		return userMapper.getAll(map);
	}
}

xml代码写成如下

<mapper namespace="com.test.dao.UserMapper">
	<select id="getAll" resultType="user" parameterType="map">
		select * from user where id=#{id} and name=#{name}
	</select>
</mapper>

除了这些测试类传进入的参数也要改变测试类写成如下

public class Test {
	public static void main(String[] args) {

		SqlSession session = null;
		session = MyBatisUtil.getSqlSession();
		UserMapper dao = new Userlmpl();

		int id = 1;
		String name = "小红";

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("id", id);
		map.put("name", name);
		List<User> list = dao.getAll(map);
		for (User user : list) {
			System.out.println(user);
		}

	}
}

#{}里面的名称对应的是 Map里面的key名称。  这种方法适合传递多个参数,且参数易变能灵活传递的情况。

方法4:Java Bean传参法

接口写成如下

public interface UserMapper {
	public List<User> getAll(User user);
}

实现类写成如下

public class Userlmpl implements UserMapper {
	private UserMapper userMapper;
	
	public Userlmpl() {
		userMapper=MyBatisUtil.getMapper(UserMapper.class);
	}
	
	@Override
	public List<User> getAll(User user) {
		return userMapper.getAll(user);
	}
}

测试类如下

public class Test {
	public static void main(String[] args) {

		SqlSession session = null;
		session = MyBatisUtil.getSqlSession();
		UserMapper dao = new Userlmpl();

		int id = 1;
		String name = "小红";
		
		User user=new User();
		user.setId(id);
		user.setName(name);
		List<User> list = dao.getAll(user);
		for (User user2 : list) {
			System.out.println(user2);
		}

	}
}

#{}里面的名称对应的是User类里面的成员属性。
这种方法很直观,但需要建一个实体类,扩展不容易,需要加属性

总结一下上面是一个包含:实体对象,普通类型,Map,多个参数的传递。

多个参数:使用注解的方式实现

实体对象:实体对象跟普通类型参数传递方法一样,只是在用的时候,以 对象名打点访问对象属性名的方式调用就可以了。

Mpa:跟普通类型参数传递方法一样用的时候,以 对象名打点访问对象属性名

其它传递,不过数据类型多复杂也是如此

在方法3中注解传参法普通类型直接注释即可,混合类型如下

@Param注解传参法拓展

当我们传入的参数包括实体,Map和参数时如何用注解,解决方法如下

首先接口写成如下

public interface UserMapper {
	public List<User> getAll(@Param("user") User user,@Param("map") Map<String, Object> map,@Param("id") Integer id,@Param("name") String name);
}

实现类如下

public class Userlmpl implements UserMapper {
	private UserMapper userMapper;
	
	public Userlmpl() {
		userMapper=MyBatisUtil.getMapper(UserMapper.class);
	}
	
	@Override
	public List<User> getAll(User user,Map<String, Object> map,Integer id,String name) {
		return userMapper.getAll(user, map, id, name);
	}
}

xml如下

<mapper namespace="com.test.dao.UserMapper">
	<select id="getAll" resultType="user">
		select * from user
		<where>
			and 1=#{user.id} and "小红"=#{user.name}
			and 1=#{map.id} and "小红"=#{map.name}
		</where>
	</select>
</mapper>
测试类如下
public class Test {
	public static void main(String[] args) {

		SqlSession session = null;
		session = MyBatisUtil.getSqlSession();
		UserMapper dao = new Userlmpl();

		int id = 1;
		String name = "小红";
		
		User user=new User();
		user.setId(id);
		user.setName(name);
		Map<String, Object> map=new HashMap<String, Object>();
		map.put("id", id);
		map.put("name",name);
		List<User> list = dao.getAll(user, map, id, name);
		for (User user2 : list) {
			System.out.println(user2);
		}

	}
}

从xml中我们看到user和map都是以打点方式来访问里面的传过来的参数,运行后测试结果打印如下

DEBUG [main] - ==>  Preparing: select * from user WHERE 1=? and "小红"=? and 1=? and "小红"=? 
DEBUG [main] - ==> Parameters: 1(Integer), 小红(String), 1(Integer), 小红(String)
DEBUG [main] - <==      Total: 3
User [id=1, name=小红, age=18]
User [id=2, name=小兰, age=19]
User [id=3, name=小鹿, age=17]

提示:sql语句中的?号 表示占位符,运行结果中可以看出来等于号前面的数值与后面的传过来参数相等。

附加Mybatis传参优化版

我们从代码中可以发现接口的实现类可以直接省略掉,传参也可以用通用的Map传参,只需要改写测试类和接口实现代码如下

接口代码

//接口
public interface UserMapper {
	public List<Map<String,Object>> getAll(Map<String,Object>);
}

测试类代码

public class Test {
	public static void main(String[] args) {

		SqlSession session = null;
		session = MyBatisUtil.getSqlSession();
		UserMapper dao =MyBatisUtil.getMapper(UserMapper.class);
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("id",1);
                map.put("name","小红");
		List<Map<String,Object>> list = dao.getAll(map);
		for (User user : list) {
			System.out.println(user);
		}

	}
}

使用Mapper接口时参数传递方式原理

Mybatis在使用Mapper接口进行编程时,其实底层是采用了动态代理机制,表面上是调用的Mapper接口,而实际上是通过动态代理调用的SqlSession的对应方法,如selectOne(),有兴趣的朋友可以查看DefaultSqlSession的getMapper()方法实现,其最终会获得一个代理了Mapper接口的MapperProxy对象。MapperProxy对象在调用Mapper接口方法时会把传递的参数做一个转换,然后把转换后的参数作为入参调用SqlSession对应的操作方法(如selectOne、insert等)。转换过程可以参考MapperMethod的execute()方法实现。简单来说是以下规则:

1、如果传递过来是单参数,且没有以@Param注解进行命名,则直接将单参数作为真实的参数调用SqlSession的对应方法。

2、如果传递过来的不是单参数或者是包含以@Param注解进行命名的参数,则会将对应的参数转换为一个Map进行传递。具体规则如下:

      2.1、 会把对应的参数按照顺序以param1、param2、paramN这样的形式作为Key存入目标Map中,第一个参数是param1,第N个参数是paramN。

      2.2、 如果参数是以@Param注解命名的参数,则以@Param指定的名称作为Key存入目标Map中。

      2.3、 如果参数不是以@Param注解命名的,则按照顺序以0、1、N这样的形式作为Key存入目标Map中,第一个参数是0,第N个参数是N。

分享到:
打赏
-版权声明-

作者: 36D小可爱, 转载或复制请以 超链接形式 并注明出处 寒江孤影
原文地址: 《Mybatis多参数及Map,实体对象传递方法案例》 发布于2021-4-11

阅读时间:   发布于:2021-4-11
文章标题:《Mybatis多参数及Map,实体对象传递方法案例》
本文链接:https://a14.cn:443/post-21.html
本文编辑: 36D小可爱,转载请注明超链接和出处寒江孤影
收录状态:[百度已收录][360已收录][搜狗已收录]

评论一下

切换注册

登录

忘记密码?

您也可以使用第三方帐号快捷登录

切换登录

注册

Mybatis多参数及Map,实体对象传递方法案例

长按图片转发给朋友

觉得文章有用就打赏一下文章作者

花呗扫一扫打赏

微信扫一扫打赏

企鹅扫一扫打赏

召唤伊斯特瓦尔