@Param注解简单介绍
@Param注解是应用在Dao层的一个注解,用于给方法参数指定名称,以便于在xml文件中的SQL语句中进行引用
什么场景需要使用@Param注解?
按照我个人的理解,当Mapper层方法的参数只有一个时,可以不用加@Param注解,
直接在SQL语句中进行参数的引用即可
(经过我的尝试,发现参数类型无论是简单类型,还是对象,或者是数组、集合,都可以不用加@Param注解)
但是如果方法的参数超过了一个,就需要添加@Param注解以区分每个参数,防止在SQL中引用时出现引用错误或者引用不到的情况。
用代码案例说明
案例一
当参数只有一个且是简单类型时:
// 根据用户ID查询用户信息 ----Mapper层代码
User getUserByUserId(int userId);
<!-- xml文件代码 -->
<select id="getUserByUserId" parameterType="int" resultType="cn.tedu.weibo.pojo.entity.User">
SELECT * FROM user WHERE id = #{userId}
</select>
注: 建议在写resultType属性规定返回结果类型时,尽量写类的全限定名(即完整的包名.类名),避免出现类绑定错误的问题
在上述代码中,getUserByUserId()方法中,只有一个int类型的参数userId,此时可以不加@Param注解,之后去xml文件中编写对应的SQL语句,需要注意的是,在SQL标签中最好手动指定parameterType的值,即方法参数的数据类型,以保证参数的合法性及安全性;
然后就可以直接在SQL语句中引用getUserByUserId()方法中的参数了,在引用时直接写参数名即可,在程序运行时,框架会自动绑定方法参数的值到SQL语句中的#{}中。
进行测试
// 测试代码
@Test
void test1(){
// 调用Mapper层方法,传入userId = 6
User user = paramTestMapper.getUserByUserId(6);
// 输出查询结果
System.out.println(user);
}
运行结果:
可以看到,当Mapper层方法的参数只有一个且为简单类型时,是可以省略@Param注解的。
案例二
参数只有一个且是对象时:
// 添加用户 ---Mapper层代码
int addUser(User user);
<!-- xml文件代码 -->
<insert id="addUser" parameterType="cn.tedu.weibo.pojo.entity.User">
INSERT INTO user
VALUES (
NULL,
#{username},
#{password},
#{nickname}
)
</insert>
在上述代码中,addUser()的参数是一个User对象,属于引用类型参数,此时也可以不用加@Param注解,直接在SQL语句中引用这个对象中的属性即可,框架会自动绑定值
进行测试
// 测试代码
@Test
void test1(){
User user = new User(); //创建一个User对象,用于后面插入
user.setUsername("岳云鹏");
user.setPassword("123");
user.setNickname("小岳岳");//设置User对象属性值
System.out.println("插入数据行数: "+paramTestMapper.addUser(user));
}//输出受影响行数,以检验是否插入成功
运行结果:
成功插入
案例二延伸案例—给对象参数user添加@Param注解
// 添加用户(使用@Param注解) ---Mapper层代码
int addUser(@Param("u") User user);
<!-- xml文件代码 -->
<insert id="addUser" parameterType="cn.tedu.weibo.pojo.entity.User">
INSERT INTO user
VALUES(
NULL,
#{u.username},
#{u.password},
#{u.nickname}
)
</insert>
在上述代码中,给addUser()方法的参数user添加了@Param注解,设置新名称为"u",此时,在xml文件中编写SQL语句中时,就需要通过"u"去引用user对象中的属性了,其实这里的"u"指的就是user对象,u.username就等于user.username,在使用上与案例二其实没有太大差别。
进行测试
// 测试代码
@Test
void test1(){
User user = new User();// 创建User对象
user.setUsername("康娜");
user.setPassword("123");
user.setNickname("康娜酱");// 给对象属性赋值
System.out.println("插入数据行数: "+paramTestMapper.addUser(user)// 查看操作结果
);
}
运行结果:
数据正常插入。
案例三
参数只有一个且参数时List集合时:
// 批量插入用户 ----Mapper层代码
int addUsers(List<User> users);
<!-- xml文件代码 -->
<insert id="addUsers" parameterType="cn.tedu.weibo.pojo.entity.User">
INSERT INTO user
VALUES
<foreach collection="list" item="user" separator=",">
(
NULL,
#{user.username},
#{user.password},
#{user.nickname}
)
</foreach>
</insert>
在上述代码中,addUsers()方法的参数为List集合,泛型指定为User类型,即该List集合是一个存储User对象的集合。在SQL语句中使用了标签对方法的参数users进行遍历,collection用于指定要遍历的数据集合的类型,item的值"user"用来表示每次遍历时获取到的元素,在当前业务中,"user"指的就是users中的user对象,separator指定Value部分之间用逗号进行分隔。SQL语句中通过item指定的值:"user"去引用user对象中的属性。同样的,这个案例中也没有使用@Param注解。
进行测试
// 测试代码
@Test
void test1(){
List<User> users = new ArrayList<>();// 准备一个List集合
for(int i = 1;i<=5;i++){// 循环生成五个User对象
User user = new User();
user.setUsername("张三"+i);
user.setPassword("123");
user.setNickname("小三"+i);// 为每个User对象赋值
users.add(user);// 将每次创建好的User对象放进users集合中
}
System.out.println("插入数据行数: "+paramTestMapper.addUsers(users)// 调用Mapper层方法并查看受影响行数
);
}
执行结果:
执行没有问题,数据成功插入。
案例四
参数只有一个且参数是数组时:
// 批量删除用户 ----Mapper层代码
int deleteUserByUserIds(int[] userIds);
<!-- xml文件代码 -->
<delete id="deleteUserByUserIds" parameterType="int">
DELETE FROM user WHERE id in
<foreach collection="array" item="userId" open="(" separator="," close=")">
#{userId}
</foreach>
</delete>
在上述代码中,deleteUserByUserIds()方法中参数类型为整型数组,则xml文件中使用标签进行遍历时,collection的值应该设置为"array",之后直接在SQL语句中引用item的值即可
进行测试
// 测试代码
@Test
void test1(){
int[] userIds = {6,7,13};// 准备一个int数组
System.out.println("受影响行数: "+paramTestMapper.deleteUserByUserIds(userIds));// 执行并查看结果
}
执行结果:
数据被成功删除。
案例五
参数超过一个时:
// 根据username和nickname查询用户信息 ---Mapper层代码
User getUserByUsernameAndNickname(@Param("usname") String username, @Param("niname") String nickname);
<!-- xml文件代码 -->
<select id="getUserByUsernameAndNickname" parameterType="String" resultType="cn.tedu.weibo.pojo.entity.User">
SELECT * FROM user WHERE username = #{usname} AND nickname = #{niname}
</select>
在上述代码中,getUserByUsernameAndNickname()方法中的参数数量为2个,超过了一个,此时就非常有必要添加@Param注解,以区分这两个参数,则xml文件中引用这两个参数时只需要引用@Param注解中value的值即可
运行流程同以上的案例,不做过多赘述。
总结
- @Param注解在持久层使用时,要根据Mapper层接口方法的参数数量来决定是否使用该注解,参数只有一个时,可以不使用该注解,但当参数数量超过了一个,此时就有必要使用@Param注解了,并给value属性赋值,以达到区分参数的目的。
- @Param注解可以修饰任何数据类型的参数
整理于 2023-08-05 13:49