🥪MyBatis操作Oracle(实现兼容Oracle和MySQL)

MyBatis操作Oracle(实现兼容Oracle和MySQL)

前言

有这样的需求,在Oracle或者MySQL中有相同的student表。
如果在后面不确定项目最后用到哪种类型的数据库的时候,可以对Oracle或者MySQL语法的xml,单独编写
因为在语法上面两种关系型数据库有些许的区别。
环境

以Oracle11g来演示,只需要创建序列,不需要创建触发器,通过ORM框架操作来生成主键

MySQL版本是8.x

代码地址:https://gitee.com/zhang-zhixi/springboot-mp-oracle-auto.git

1、分别创建Student表

Oracle:

CREATE TABLE "STUDENT" (
  "ID" NUMBER NOT NULL,
  "NAME" VARCHAR2(255 BYTE),
  "AGE" NUMBER(2,0),
  "SEX" NVARCHAR2(2),
  "TEL" NUMBER,
  "EMAIL" VARCHAR2(255 BYTE),
  "BIRTHDAY" DATE,
  "CREATE_TIME" DATE,
  "UPDATE_TIME" DATE,
  "IS_DELETED" NUMBER,
  CONSTRAINT "PK_STUDENT" PRIMARY KEY ("ID")
);

COMMENT ON COLUMN "STUDENT"."ID" IS '主键';
COMMENT ON COLUMN "STUDENT"."NAME" IS '姓名';
COMMENT ON COLUMN "STUDENT"."AGE" IS '年龄';
COMMENT ON COLUMN "STUDENT"."SEX" IS '性别';
COMMENT ON COLUMN "STUDENT"."TEL" IS '电话号码';
COMMENT ON COLUMN "STUDENT"."EMAIL" IS '电子邮箱';
COMMENT ON COLUMN "STUDENT"."BIRTHDAY" IS '生日';
COMMENT ON COLUMN "STUDENT"."CREATE_TIME" IS '创建时间';
COMMENT ON COLUMN "STUDENT"."UPDATE_TIME" IS '更新时间';
COMMENT ON COLUMN "STUDENT"."IS_DELETED" IS '是否删除(0-未删除,1已删除)';

MySQL:

CREATE TABLE `student`  (
  `ID` int NOT NULL AUTO_INCREMENT,
  `NAME` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '姓名',
  `AGE` int NULL DEFAULT NULL COMMENT '年龄',
  `SEX` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',
  `TEL` int NULL DEFAULT NULL COMMENT '电话号码',
  `EMAIL` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '电子邮箱',
  `BIRTHDAY` date NULL DEFAULT NULL COMMENT '生日',
  `CREATE_TIME` date NULL DEFAULT NULL COMMENT '创建时间',
  `UPDATE_TIME` date NULL DEFAULT NULL COMMENT '更新时间',
  `IS_DELETED` int NULL DEFAULT NULL COMMENT '是否删除(0:未删除,1:已删除)',
  PRIMARY KEY (`ID`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1000 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;

2、为Oracle创建序列

create sequence SEQ_STUDENT_ID
    minvalue 1 			--最小值
    nomaxvalue 			--不设置最大值(由机器决定),或 根据表字段的值范围设置 maxvalue
    start with 1 		--从1开始计数,数值可变
    increment by 1 	--每次加1,数值可变
    nocycle 				--nocycle:一直累加,不循环;cycle:达到最大值后,将从头开始累加
		-- 		nocache:在内存中不缓存序列的值;cache在内存中缓存序列的值
    nocache; 

3、application.properties数据库配置

# 数据库配置:Oracle
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@(description=(address=(protocol=tcp)(port=1521)(host=127.0.0.1)(PORT = 1521))(connect_data=(SERVER = DEDICATED)(service_name=orcl)))
spring.datasource.username=xxx
spring.datasource.password=xxx

# 数据库配置:MySQL
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
#spring.datasource.username=xxx
#spring.datasource.password=xxx

4、业务代码

实体:

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "STUDENT")
public class Student implements Serializable {
    /**
     * 主键
     */
    @TableId(value = "ID", type = IdType.AUTO)
    private Long id;

    /**
     * 姓名
     */
    @TableField(value = "NAME")
    private String name;

    /**
     * 年龄
     */
    @TableField(value = "AGE")
    private Integer age;

    /**
     * 性别
     */
    @TableField(value = "SEX")
    private String sex;

    /**
     * 电话号码
     */
    @TableField(value = "TEL")
    private Long tel;

    /**
     * 电子邮箱
     */
    @TableField(value = "EMAIL")
    private String email;

    /**
     * 生日
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    @TableField(value = "BIRTHDAY")
    private Date birthday;

    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    @TableField(value = "CREATE_TIME")
    private Date createTime;

    /**
     * 更新时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    @TableField(value = "UPDATE_TIME")
    private Date updateTime;

    /**
     * 是否删除(0-未删除,1已删除)
     */
    @TableField(value = "IS_DELETED")
    private Long isDeleted;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

Mybati配置(***):

@Configuration
public class MybatisConfig {
    /**
     * DatabaseIdProvider元素主要是为了支持不同的数据库
     * @return 数据库标识
     */
    @Bean
    public DatabaseIdProvider getDatabaseIdProvider() {
        DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
        Properties properties = new Properties();
        properties.setProperty("Oracle", "oracle");
        properties.setProperty("MySQL", "mysql");
        databaseIdProvider.setProperties(properties);
        return databaseIdProvider;
    }
}

Mapper.xml

第一种方法,实现Oracle和MySQL插入数据:可以维护两套插入语句,需要指定标签参数databaseId

Oracle不支持主键自增,可以通过selectKey标签来访问序列来生成ID

<insert id="insertUserToMybatis" parameterType="com.zhixi.pojo.Student" databaseId="oracle">
        <selectKey order="BEFORE" resultType="java.lang.Long" keyProperty="id">
            SELECT SEQ_STUDENT_ID.NEXTVAL FROM DUAL
        </selectKey>
        insert into STUDENT
        <trim prefix="(" suffix=")" suffixOverrides=",">
            ID,
            <if test="name != null and name != '' ">NAME,</if>
            <if test="age != null and age != '' ">AGE,</if>
            <if test="sex != null and sex != '' ">SEX,</if>
            <if test="tel != null and tel != '' ">TEL,</if>
            <if test="email != null and email != '' ">EMAIL,</if>
            <if test="updateTime != null">UPDATE_TIME,</if>
            IS_DELETED,CREATE_TIME
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{id},
            <if test="name != null and name != '' ">#{name},</if>
            <if test="age != null and age != '' ">#{age},</if>
            <if test="sex != null and sex != '' ">#{sex},</if>
            <if test="tel != null and tel != '' ">#{tel},</if>
            <if test="email != null and email != '' ">#{email},</if>
            <if test="updateTime != null">#{updateTime},</if>
            0,
            sysdate
        </trim>
    </insert>

    <insert id="insertUserToMybatis" parameterType="com.zhixi.pojo.Student" databaseId="mysql">
        insert into STUDENT
        <trim prefix="(" suffix=")" suffixOverrides=",">
            ID,
            <if test="name != null and name != '' ">NAME,</if>
            <if test="age != null and age != '' ">AGE,</if>
            <if test="sex != null and sex != '' ">SEX,</if>
            <if test="tel != null and tel != '' ">TEL,</if>
            <if test="email != null and email != '' ">EMAIL,</if>
            <if test="updateTime != null">UPDATE_TIME,</if>
            IS_DELETED,CREATE_TIME
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{id},
            <if test="name != null and name != '' ">#{name},</if>
            <if test="age != null and age != '' ">#{age},</if>
            <if test="sex != null and sex != '' ">#{sex},</if>
            <if test="tel != null and tel != '' ">#{tel},</if>
            <if test="email != null and email != '' ">#{email},</if>
            <if test="updateTime != null">#{updateTime},</if>
            0,
            now()
        </trim>
    </insert>

第二种方法:通过_databaseId来判断是否通过序列生成ID

此处判断的是ID和创建时间,来作为区分MySQL和Oracle依据,因为Oracle需要通过序列创建ID,并且MySQL和Oracle中时间函数也不一样,如下:

<insert id="insertUserToMybatis" parameterType="com.zhixi.pojo.Student">
    insert into STUDENT
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="_databaseId == 'oracle' ">ID,</if>
        <if test="name != null and name != '' ">NAME,</if>
        <if test="age != null and age != '' ">AGE,</if>
        <if test="sex != null and sex != '' ">SEX,</if>
        <if test="tel != null and tel != '' ">TEL,</if>
        <if test="email != null and email != '' ">EMAIL,</if>
        <if test="updateTime != null">UPDATE_TIME,</if>
        IS_DELETED,CREATE_TIME
    </trim>
    values
    <trim prefix="(" suffix=")" suffixOverrides=",">
        /*判断是否是Oracle,是Oracle就通过序列生成ID*/
        <if test="_databaseId == 'oracle' ">SEQ_STUDENT_ID.NEXTVAL,</if>
        <if test="name != null and name != '' ">#{name},</if>
        <if test="age != null and age != '' ">#{age},</if>
        <if test="sex != null and sex != '' ">#{sex},</if>
        <if test="tel != null and tel != '' ">#{tel},</if>
        <if test="email != null and email != '' ">#{email},</if>
        <if test="updateTime != null">#{updateTime},</if>
        0,
        <choose>
            <when test="_databaseId == 'mysql' ">
                now()
            </when>
            <when test="_databaseId == 'oracle' ">
                sysdate
            </when>
        </choose>
    </trim>
</insert>

5、测试:

自行测试即可;

@Test
void insertStudentToMybatis() throws ParseException {
    Student student = new Student();
    student.setName("张三");
    student.setAge(23);
    student.setSex("男");
    student.setTel(1888888888L);
    student.setEmail("1820712542@qq.com");
    student.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("2000-03-05"));
    student.setUpdateTime(new Date());
    studentService.insertUserToMybatis(student);
}

  

 

posted @ 2023-09-07 20:53  Java小白的搬砖路  阅读(2189)  评论(0编辑  收藏  举报