Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Cập nhật hàng loạt với MyBatis và các thủ tục được lưu trữ Oracle

Một thủ tục có thể nhận các tham số kiểu bảng và bạn có thể viết một trình xử lý kiểu tùy chỉnh để thực hiện chuyển đổi.

Có thể dễ dàng giải thích hơn bằng cách sử dụng các đối tượng cụ thể.
Thay vì MY_TYPE , Tôi sẽ sử dụng S_USER_OBJ ...

create or replace type S_USER_OBJ as object (
  id integer,
  name varchar(20)
);

... một bảng ...

create table users (
  id integer,
  name varchar(20)
);

... và một POJO.

public class User {
  private Integer id;
  private String name;
  // setter/getter
}

Đây là kiểu mới là tập hợp của S_USER_OBJ .

create or replace type S_USER_OBJ_LIST as table of S_USER_OBJ;

Thủ tục có thể lấy kiểu bảng làm tham số. ví dụ:

create or replace procedure doUpdate(
  user_list in S_USER_OBJ_LIST,
  user_out out S_USER_OBJ_LIST
) is
begin
  -- process IN param
  for i in user_list.first .. user_list.last loop
    update users
      set name = user_list(i).name)
      where id = user_list(i).id;
  end loop;
  -- set OUT param
  select * bulk collect into user_out
    from (
      select S_USER_OBJ(u.id, u.name) from users u
    );
end;

Người lập bản đồ sẽ trông như sau:

void doUpdate(
  @Param("users") List<User> users,
  @Param("outParam") Map<String, ?> outParam);
<update id="doUpdate" statementType="CALLABLE">
  {call doUpdate(
    #{users,typeHandler=pkg.UserListTypeHandler},
    #{outParam.outUsers,jdbcType=ARRAY,jdbcTypeName=S_USER_OBJ_LIST,mode=OUT,typeHandler=pkg.UserListTypeHandler}
  )}
</update>

UserListTypeHandler là một trình xử lý kiểu tùy chỉnh chuyển đổi List<User> đến / từ một ARRAY của STRUCT .

import java.math.BigDecimal;
import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import oracle.jdbc.driver.OracleConnection;

public class UserListTypeHandler extends
    BaseTypeHandler<List<User>>{

  @Override
  public void setNonNullParameter(
      PreparedStatement ps, int i, List<User> parameter,
      JdbcType jdbcType) throws SQLException {
    Connection conn = ps.getConnection();
    List<Struct> structs = new ArrayList<Struct>();
    for (int idx = 0; idx < parameter.size(); idx++) {
      User user = parameter.get(idx);
      Object[] result = { user.getId(), user.getName() };
      structs.add(conn.createStruct("S_USER_OBJ", result));
    }
    Array array = ((OracleConnection) conn)
      .createOracleArray("S_USER_OBJ_LIST",
      structs.toArray());
    ps.setArray(i, array);
    array.free();
  }

  @Override
  public List<User> getNullableResult(
      CallableStatement cs,
      int columnIndex) throws SQLException {
    List<User> result = new ArrayList<>();
    Array array = cs.getArray(columnIndex);
    Object[] objs = (Object[]) array.getArray();
    for (Object obj : objs) {
      Object[] attrs = ((Struct) obj).getAttributes();
      result.add(new User(
        ((BigDecimal) attrs[0]).intValue(),
        (String) attrs[1]));
    }
    array.free();
    return result;
  }
  ...
}

Mã sử ​​dụng phương thức sẽ trông giống như thế này.

Map<String, ?> outParam = new HashMap<>();
mapper.doUpdate(userList, outParam);
List<User> outUsers = outParam.get("outUsers");

Đối với OUT tham số, cũng có một cách khác là sử dụng con trỏ và ánh xạ kết quả.
Trong câu lệnh ánh xạ, chỉ định tham số OUT như sau.

#{outParam.outUsers,jdbcType=CURSOR,javaType=java.sql.ResultSet,mode=OUT,resultMap=userRM}

Bản đồ kết quả khá đơn giản.

<resultMap type="test.User" id="userRM">
  <id property="id" column="id" />
  <result property="name" column="name" />
</resultMap>

Trong thủ tục, khai báo tham số OUT là SYS_REFCURSOR

create or replace procedure doUpdate(
  user_list in S_USER_OBJ_LIST,
  user_out out SYS_REFCURSOR
) is
begin
  ...
  -- set OUT param
  open user_out for select * from users;
end;

Đây là bản trình diễn có thể thực thi:
https://github .com / harawata / mybatis-Problem / tree / master / so-56834806




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thủ tục lưu trữ Oracle với các tham số cho mệnh đề IN

  2. N giá trị khác biệt hàng đầu của một cột trong Oracle

  3. Tránh sự cố với BigDecimal khi chuyển sang Java 1.4 sang Java 1.5+

  4. Phương pháp thu thập:Thủ tục DELETE trong Cơ sở dữ liệu Oracle

  5. CachedRowSet chậm hơn ResultSet?