0%

11.3 注解调用存储过程

11.3 注解调用存储过程

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
E:\workspace_web2\MyAProcedureTest
├─src
│ ├─db.properties
│ ├─domain
│ │ └─User.java
│ ├─fractory
│ │ └─SqlSessionFratoryTools.java
│ ├─log4j.xml
│ ├─mapper
│ │ └─UserMapper.java
│ ├─mybatis-config.xml
│ ├─procedure.sql
│ ├─tb_user.sql
│ └─test
│ ├─DeleteTest.java
│ ├─InsertTest.java
│ ├─SelectAllTest.java
│ ├─SelectByIdTest.java
│ └─UpdateTest.java
└─WebContent
├─META-INF
│ └─MANIFEST.MF
└─WEB-INF
└─lib
├─commons-logging-1.2.jar
├─log4j-1.2.17.jar
├─log4j-api-2.3.jar
├─log4j-core-2.3.jar
├─mybatis-3.4.5.jar
└─mysql-connector-java-5.1.44-bin.jar

数据库表

tb_user.sql:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建数据表
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(18) DEFAULT NULL,
`sex` char(2) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 插入数据
INSERT INTO `tb_user` VALUES ('1', '小明', '男', '21');
INSERT INTO `tb_user` VALUES ('2', '小王', '男', '22');
INSERT INTO `tb_user` VALUES ('3', '小丽', '女', '18');
INSERT INTO `tb_user` VALUES ('4', '小芳', '女', '18');

创建存储过程

procedure.sql:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 创建insert_user存储过程
drop procedure if exists insert_user;
DELIMITER &&
CREATE PROCEDURE insert_user (
OUT v_id int,
in v_name varchar(18),
in v_sex varchar(19),
in v_age int
)
BEGIN
INSERT INTO tb_user (name,sex,age) VALUES (v_name,v_sex,v_age);
SET v_id=LAST_INSERT_ID();
END
&&
DELIMITER ;
# 创建select_user存储过程
drop procedure if exists select_all_user;
delimiter &&
create procedure select_all_user()
begin
select id,name,sex,age from tb_user;
end
&&
DELIMITER ;
# 创建select_user_by_id存储过程
drop procedure if exists select_user_by_id;
DELIMITER &&
create procedure select_user_by_id(IN in_id INTEGER)
begin
select id,name,sex,age from tb_user where id=in_id;
end
&&
DELIMITER ;
# 创建update_user_by_id存储过程
drop procedure if exists update_user_by_id;
delimiter &&
create procedure update_user_by_id (
IN p_id int,
IN p_name varchar(18),
IN p_sex varchar(19),
IN p_age int
)
begin
update tb_user set name=p_name,sex=p_sex,age=p_age
where id=p_id;
end
&&
delimiter ;
# 创建delete_user_by_id存储过程
drop procedure if exists delete_user_by_id;
delimiter &&
create procedure delete_user_by_id(IN p_id integer)
begin
delete from tb_user where id=p_id;
end
&&
delimiter ;

持久化对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package domain;
public class User{
private Integer id;
private String name;
private String sex;
private Integer age;
public User()
{
super();
}
// 此处省略getter和setter方法,请自己补上
@Override
public String toString()
{
return "User [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
}

mapper接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package mapper;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.mapping.StatementType;
import domain.User;
public interface UserMapper{
/**
* 查询所有的用户信息.
*
* @return 包含所有用户信息的List集合.
*/
@Select("{call select_all_user()}")
@Options(statementType=StatementType.CALLABLE)
List<User> selectAllUser();
/**
* 根据id查询用户信息.
* @param id
* @return
*/
@Select("{call select_user_by_id(#{id,mode=IN})}")
@Options(statementType=StatementType.CALLABLE)
User selectUserById(Integer id);
/**
* 插入一个用户信息.
* @param user
* @return
*/
@Insert("{call insert_user("
+ "#{id,mode=OUT,jdbcType=INTEGER},"
+ "#{name,mode=IN},"
+ "#{sex,mode=IN},"
+ "#{age,mode=IN}"
+ ")}")
@Options(statementType=StatementType.CALLABLE)
Integer insertUser(User user);
/**
* 根据id更新用户信息.
*/
@Update("{call update_user_by_id("
+ "#{id,mode=IN},"
+ "#{name,mode=IN},"
+ "#{sex,mode=IN},"
+ "#{age,mode=IN}"
+ ")}")
@Options(statementType=StatementType.CALLABLE)
void updateUserById(User user);
/**
* 根据id删除用户.
* @param id
*/
@Delete("{call delete_user_by_id(#{id,mode=IN})}")
@Options(statementType=StatementType.CALLABLE)
void deleteUserById(Integer id);
}

UserMapper.java只是将之前写在XML文件当中调用存储过程的SQL语句写在了注解当中,注意需要使用@Options(statementType=StatementType.CALLABLE)提供调用存储过程的CALLBALE选项,其他并无不同。

调用存储过程查询select操作

查询全部

存储过程如下:

1
2
3
4
5
6
7
8
9
# 创建select_user存储过程
drop procedure if exists select_all_user;
delimiter &&
create procedure select_all_user()
begin
select id,name,sex,age from tb_user;
end
&&
DELIMITER ;

查询所有的mapper接口方法如下:

1
2
3
@Select("{call select_all_user()}")
@Options(statementType=StatementType.CALLABLE)
List<User> selectAllUser();

select_all_user这个存储过程没有参数,直接在前面加上call调用即可,注意存储过程时不要忘了加上括号,也就是:call 存储过程名称 括号,
还有就是放在注解中的存储过程调用语句要用大括号包裹起来,至于为什么,我还不知道,先这样背着.

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package test;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import domain.User;
import fractory.SqlSessionFratoryTools;
import mapper.UserMapper;
public class SelectAllTest{
public static void main(String[] args)
{
SqlSession sqlSession = null;
try
{
// 加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFratoryTools.getSqlSession();
// 获取mapper接口代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAllUser();
System.out.println("----------------------------------");
users.forEach(user-> System.out.println(user));
// 提交事务
sqlSession.commit();
} catch (Exception e)
{
// 出错回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally
{
// 关闭会话
if(sqlSession != null)
sqlSession.close();
}
}
}

运行效果

1
2
3
4
5
6
7
8
9
DEBUG [main] ==>  Preparing: {call select_all_user()} 
DEBUG [main] ==> Parameters:
DEBUG [main] <== Total: 4
DEBUG [main] <== Updates: 0
----------------------------------
User [id=1, name=小明, sex=男, age=21]
User [id=2, name=小王, sex=男, age=22]
User [id=3, name=小丽, sex=女, age=18]
User [id=4, name=小芳, sex=女, age=18]

根据id查询

用到的存储过程如下:

1
2
3
4
5
6
7
8
9
# 创建select_user_by_id存储过程
drop procedure if exists select_user_by_id;
DELIMITER &&
create procedure select_user_by_id(IN in_id INTEGER)
begin
select id,name,sex,age from tb_user where id=in_id;
end
&&
DELIMITER ;

mapper接口方法如下:

1
2
3
@Select("{call select_user_by_id(#{id,mode=IN})}")
@Options(statementType=StatementType.CALLABLE)
User selectUserById(Integer id);

注意存储过程的参数写法,#{id,mode=IN}这个是mybatis的表达式,该表达式中第一项id是参数名称,第二项mode=IN表示这个参数是存储过程的输入参数。

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package test;
import org.apache.ibatis.session.SqlSession;
import domain.User;
import fractory.SqlSessionFratoryTools;
import mapper.UserMapper;
public class SelectByIdTest{
public static void main(String[] args)
{
SqlSession sqlSession = null;
try
{
// 加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFratoryTools.getSqlSession();
// 获取mapper接口代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectUserById(1);
System.out.println("-----------------------------------------------");
System.out.println(user);
// 提交事务
sqlSession.commit();
} catch (Exception e)
{
// 出错回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally
{
// 关闭会话
if(sqlSession != null)
sqlSession.close();
}
}
}

运行效果如下:

1
2
3
4
5
6
DEBUG [main] ==>  Preparing: {call select_user_by_id(?)} 
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <== Total: 1
DEBUG [main] <== Updates: 0
-----------------------------------------------
User [id=1, name=小明, sex=男, age=21]

使用存储过程进行update操作

对应的存储过程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 创建update_user_by_id存储过程
drop procedure if exists update_user_by_id;
delimiter &&
create procedure update_user_by_id (
IN p_id int,
IN p_name varchar(18),
IN p_sex varchar(19),
IN p_age int
)
begin
update tb_user set name=p_name,sex=p_sex,age=p_age
where id=p_id;
end
&&
delimiter ;

mapper接口方法如下:

1
2
3
4
5
6
7
8
@Update("{call update_user_by_id("
+ "#{id,mode=IN},"
+ "#{name,mode=IN},"
+ "#{sex,mode=IN},"
+ "#{age,mode=IN}"
+ ")}")
@Options(statementType=StatementType.CALLABLE)
void updateUserById(User user);

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package test;
import org.apache.ibatis.session.SqlSession;
import domain.User;
import fractory.SqlSessionFratoryTools;
import mapper.UserMapper;
public class UpdateTest{
public static void main(String[] args)
{
SqlSession sqlSession = null;
try
{
// 加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFratoryTools.getSqlSession();
// 获取mapper接口代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectUserById(3);
System.out.println("----------------------------------");
if(user != null)
{
System.out.println("更新之前的数据:" + user);
System.out.println("----------------------------------");
user.setName("李四");
user.setSex("男");
user.setAge(22);
userMapper.updateUserById(user);
System.out.println("----------------------------------");
user = userMapper.selectUserById(user.getId());
System.out.println("----------------------------------");
System.out.println("更新之后的数据:" + user);
}
// 提交事务
sqlSession.commit();
} catch (Exception e)
{
// 出错回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally
{
// 关闭会话
if(sqlSession != null)
sqlSession.close();
}
}
}

运行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DEBUG [main] ==>  Preparing: {call select_user_by_id(?)} 
DEBUG [main] ==> Parameters: 3(Integer)
DEBUG [main] <== Total: 1
DEBUG [main] <== Updates: 0
----------------------------------
更新之前的数据:User [id=3, name=小丽, sex=女, age=18]
----------------------------------
DEBUG [main] ==> Preparing: {call update_user_by_id(?,?,?,?)}
DEBUG [main] ==> Parameters: 3(Integer), 李四(String), 男(String), 22(Integer)
DEBUG [main] <== Updates: 1
----------------------------------
DEBUG [main] ==> Preparing: {call select_user_by_id(?)}
DEBUG [main] ==> Parameters: 3(Integer)
DEBUG [main] <== Total: 1
DEBUG [main] <== Updates: 0
----------------------------------
更新之后的数据:User [id=3, name=李四, sex=男, age=22]

调用存储过程进行delete操作

测试的存储过程如下:

1
2
3
4
5
6
7
8
9
# 创建delete_user_by_id存储过程
drop procedure if exists delete_user_by_id;
delimiter &&
create procedure delete_user_by_id(IN p_id integer)
begin
delete from tb_user where id=p_id;
end
&&
delimiter ;

对应的mapper接口方法如下:

1
2
3
@Delete("{call delete_user_by_id(#{id,mode=IN})}")
@Options(statementType=StatementType.CALLABLE)
void deleteUserById(Integer id);

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package test;
import org.apache.ibatis.session.SqlSession;
import domain.User;
import fractory.SqlSessionFratoryTools;
import mapper.UserMapper;
public class DeleteTest{
public static void main(String[] args)
{
SqlSession sqlSession = null;
try
{
// 加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFratoryTools.getSqlSession();
// 获取mapper接口代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectUserById(2);
if(user != null)
{
System.out.println("------------------------------------------");
System.out.println("即将删除用户:" + user);
System.out.println("------------------------------------------");
userMapper.deleteUserById(user.getId());
}
// 提交事务
sqlSession.commit();
} catch (Exception e)
{
// 出错回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally
{
// 关闭会话
if(sqlSession != null)
sqlSession.close();
}
}
}

运行效果:

1
2
3
4
5
6
7
8
9
10
DEBUG [main] ==>  Preparing: {call select_user_by_id(?)} 
DEBUG [main] ==> Parameters: 2(Integer)
DEBUG [main] <== Total: 1
DEBUG [main] <== Updates: 0
------------------------------------------
即将删除用户:User [id=2, name=小王, sex=男, age=22]
------------------------------------------
DEBUG [main] ==> Preparing: {call delete_user_by_id(?)}
DEBUG [main] ==> Parameters: 2(Integer)
DEBUG [main] <== Updates: 1

调用存储过程进行insert操作

用到的存储过程定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 创建insert_user存储过程
drop procedure if exists insert_user;
DELIMITER &&
CREATE PROCEDURE insert_user (
OUT v_id int,
in v_name varchar(18),
in v_sex varchar(19),
in v_age int
)
BEGIN
INSERT INTO tb_user (name,sex,age) VALUES (v_name,v_sex,v_age);
SET v_id=LAST_INSERT_ID();
END
&&
DELIMITER ;

对应的mapper接口的方法:

1
2
3
4
5
6
7
8
@Insert("{call insert_user("
+ "#{id,mode=OUT,jdbcType=INTEGER},"
+ "#{name,mode=IN},"
+ "#{sex,mode=IN},"
+ "#{age,mode=IN}"
+ ")}")
@Options(statementType=StatementType.CALLABLE)
Integer insertUser(User user);

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package test;
import org.apache.ibatis.session.SqlSession;
import domain.User;
import fractory.SqlSessionFratoryTools;
import mapper.UserMapper;
public class InsertTest{
public static void main(String[] args)
{
SqlSession sqlSession = null;
try
{
// 加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFratoryTools.getSqlSession();
// 获取mapper接口代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setName("小张");
user.setSex("男");
user.setAge(22);
userMapper.insertUser(user);
System.out.println("---------------------------------------");
System.out.println("生成的主键:" + user.getId());
// 提交事务
sqlSession.commit();
} catch (Exception e)
{
// 出错回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally
{
// 关闭会话
if(sqlSession != null)
sqlSession.close();
}
}
}

运行效果如下:

1
2
3
4
5
DEBUG [main] ==>  Preparing: {call insert_user(?,?,?,?)} 
DEBUG [main] ==> Parameters: 小张(String), 男(String), 22(Integer)
DEBUG [main] <== Updates: 1
---------------------------------------
生成的主键:5

原文链接: 11.3 注解调用存储过程