Reputation: 123
I am unable to figure out how to send a list as a parameter to SQL Server Stored Procedure using myBatis
call sp(List<Object>)
I have a stored procedure inside a SQL Server(2012) which takes a parameter of type list.
CREATE TypeTable of Table
(
@FKId IN
@FKId INT
@FKId INT
@FKId INT
@FKId INT
@userName VARCHAR
)
My Stored Procedure call
ALTER PROCEDURE SP(@TypeTableList Typetable READONLY )
AS
BEGIN
/* My DB Operations To Enter New Records and Thier Child Records */
END
MyMapper
<select id="mapperId" parameterType="map" statementType="CALLABLE">
call sp(#{list})
</select>
POJO
public class ListClass {
private Long fk1;
private Long fk2;
private Long fk3;
private Long fk4;
private Long fk5;
private String userName;
public ListClass() {
super();
}
public Long getFk1() {
return fk1;
}
public void setFk1(Long fk1) {
this.fk1 = fk1;
}
public Long getFk2() {
return fk2;
}
public void setFk2(Long fk2) {
this.fk2 = fk2;
}
public Long getFk3() {
return fk3;
}
public void setFk3(Long fk3) {
this.fk3 = fk3;
}
public Long getFk4() {
return fk4;
}
public void setFk4(Long fk4) {
this.fk4 = fk4;
}
public Long getFk5() {
return fk5;
}
public void setFk5(Long fk5) {
this.fk5 = fk5;
}
public String getuserName() {
return userName;
}
public void setuserName(String userName) {
this.userName = userName;
}
}
I have tried using type handler of type array but i always get a exception.
I have not found any resources on creating a custom type handler for ArrayList With SQL Server
Any Help would be appriciated
Thankyou
Upvotes: 1
Views: 5075
Reputation: 3594
The create
statement you posted didn't work in SQL Server 2017, so I'll show you a simpler example.
DDLs:
create table Users (
id int,
name varchar(20)
);
create type UserTableType as table (
id int,
name varchar(20)
);
create procedure uspAddUsers
@UserTable UserTableType READONLY
as
begin
insert into Users (id, name)
select * from @UserTable
end;
POJO:
public class User {
private Integer id;
private String name;
// getter/setter
}
Mapper method:
@Options(statementType = StatementType.CALLABLE)
@Insert("{call uspAddUsers(#{users,typeHandler=pkg.UserListTypeHandler})}")
void insertUsers(@Param("users") List<User> users);
Note the typeHandler
option.
As David Browne pointed out, the driver requires SQLServerDataType
as the input, so you may need a type handler that converts the list into a SQLServerDataType
.
The below is a simple type handler implementation.
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.microsoft.sqlserver.jdbc.SQLServerDataTable;
import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement;
public class UserListTypeHandler extends BaseTypeHandler<List<User>>{
@Override
public void setNonNullParameter(PreparedStatement ps,
int i, List<User> parameter, JdbcType jdbcType)
throws SQLException {
SQLServerDataTable dataTable = new SQLServerDataTable();
dataTable.addColumnMetadata("id", java.sql.Types.INTEGER);
dataTable.addColumnMetadata("name", java.sql.Types.VARCHAR);
for (User user : parameter) {
dataTable.addRow(user.getId(), user.getName());
}
ps.unwrap(SQLServerPreparedStatement.class)
.setStructured(i, "UserTableType", dataTable);
}
// getNullableResult() won't be used
}
An executable demo tested with...
Upvotes: 2