起因
由於需要將新數據同步到另外的數據庫,所以需要使用dblink
進行操作,但是dblink不支持寫入操作,因此需要調用寫好的存儲過程才能實現將新數據插入新數據的同時插入舊數據庫。
準備工作
預先準備好新舊兩個數據庫
舊的數據庫
create table OLD_USER
(
USER_ID NUMBER(6) not null primary key,
LOGIN_NAME VARCHAR2(100) not null,
REAL_NAME VARCHAR2(300),
PASSWORD CHAR(64)
)
新的數據庫
create table NEW_USER
(
ID NUMBER(11) not null primary key,
CREATE_TIME TIMESTAMP(6),
UPDATE_TIME TIMESTAMP(6),
DELETED NUMBER(1),
ACCOUNT VARCHAR2(255),
USERNAME VARCHAR2(255),
PASSWORD VARCHAR2(255)
)
對應的實體爲:
package com.donlex.demo.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.Date;
import java.util.List;
@Getter
@Setter
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel("新數據庫對應實體")
@KeySequence("s_old_user")
public class NewUser {
@ApiModelProperty("主鍵")
@TableId(type = IdType.INPUT)
private Long id;
@ApiModelProperty(value = "創建時間", hidden = true)
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@ApiModelProperty(value = "更新時間", hidden = true)
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
@ApiModelProperty(value = "刪除標誌", hidden = true)
@TableField(fill = FieldFill.INSERT)
@TableLogic
private Boolean deleted;
@ApiModelProperty("用戶賬號")
private String account;
@ApiModelProperty("用戶名稱")
private String username;
@ApiModelProperty("密碼")
private String password;
@ApiModelProperty("插入舊數據庫返回的id")
@TableField(exist = false)
private Integer oldUserId;
}
創建存儲過程
創建一個存儲過程用於將新數據庫的數據字段和舊的數據庫字段映射上,同時使用序列自增作爲id值,將新數據插入舊數據庫中。
create or replace procedure PRO_TO_OLD_USER(
v_account in varchar2,
v_username in varchar2,
v_password in varchar2,
v_result out varchar2) is
V_ID number;
PRAGMA AUTONOMOUS_TRANSACTION;
begin
-- 使用序列自增做爲主鍵,s_old_user爲序列名, @dklinkName 是dblink名
SELECT s_old_user.NEXTVAL @dklinkName into V_ID FROM DUAL;
insert into OLD_USER(USER_ID,
LOGIN_NAME,
REAL_NAME,
PASSWORD
)
VALUES (V_ID,
-- 使用case進行判斷 v_account 字段是否爲空
case when v_account is null
then
'空'
else
v_account
end,
v_username,
v_password
);
commit;
-- 返回自增的序列值
v_result := V_ID;
DBMS_OUTPUT.put_line('添加到舊數據庫賬號成功ID爲' || V_ID);
end PRO_TO_OLD_USER;
創建mapper中的方法
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.donlex.demo.mapper.NewUserMapper">
<!-- statementType 聲明指向的是什麼類型,其中CALLABLE是執行存儲過程和函數的-->
<select id="insertIntoOldUser" statementType="CALLABLE" parameterType="com.donlex.demo.entity.NewUser">
{call PRO_TO_OLD_USER
(
#{account,mode=IN},
#{username,mode=IN},
#{password,mode=IN},
#{oldUserId,mode=OUT,jdbcType=INTEGER}
)
}
</select>
</mapper>
注意點:
statementType
設置爲CALLABLE
- 在存儲過程中使用參數時,除了寫上必要的屬性名外,還必須指定參數的 mode(模式),可選值爲
IN
、OUT
、INOUT
三種,入參使用 IN,出參使用 OUT,輸入輸出參數使用 INOUT。 - OUT 模式的參數,必須指定 jdbcType。因爲在 IN 模式下,MyBatis 提供了默認的 jdbcType,在 OUT 模式下沒有提供,因此必須指定
jdbcType
- 當入參存在無法識別,執行報錯時,最好指定
jdbcType
創建mapper接口
@Mapper
@Repository
public interface NewUserMapper extends BaseMapper<NewUser> {
/**
*
* 將新數據新增的賬號插入舊數據庫
* @author donlex
* @param req
*/
void insertIntoOldUser(NewUser req);
}
這裏定義的是void
方法,但是實際上是會返回NewUser
實體對象,所以可以通過get方法獲取屬性值,這就是爲什麼在實體中定義了一個oldUserId
,但是它不是數據表中真實存在的字段 @TableField(exist = false)
創建controller方法
這裏爲了方便就直接在controller
中寫方法調用了。
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
public class SysUserController {
@Autowired
private NewUserMapper newUserMapper;
@ApiOperation("將新數據寫入舊數據庫中")
@PostMapping("/test")
public Boolean addNewUserToOldUser(NewUser newUser){
newUserMapper.insertIntoNewUser(newsUser);
log.info("oldUserId爲{}",newUser.getOldUserId())
}
}
執行的debug日誌
2019-12-30 15:58:31.850 DEBUG ==> Preparing: {call PRO_TO_OLD_USER ( ?, ?, ?, ? ) }
2019-12-30 15:58:31.885 DEBUG ==> Parameters: 357869(String), donlex(String), a493fe7c29ce(String), 0(Integer)
歡迎訪問我的個人博客站點:https://donlex.cn