🥪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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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创建序列
1 2 3 4 5 6 7 8 | 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数据库配置
1 2 3 4 5 6 7 8 9 10 11 | # 数据库配置: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、业务代码
实体:
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 59 60 61 62 63 64 65 66 67 68 69 70 71 | @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配置(***):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @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
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 | <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中时间函数也不一样,如下:
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 | <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、测试:
自行测试即可;
1 2 3 4 5 6 7 8 9 10 11 12 | @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); } |
分类:
微服务框架
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了