加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Oracle到MySQL数据库迁移之--主键生成策略替换

发布时间:2020-12-12 15:18:23 所属栏目:百科 来源:网络整理
导读:Oracle数据库到MySQL数据库迁移过程中的一大难题就是主键生成策略的替换. 如果之前的程序中使用Oracle的 Sequence 机制来实现主键的自增的话. MySQL中需要使用 TableGenerator 进行等价替换. 替换的时候,主要有三个地方需要修改: 以注解方式完成hibernate映

Oracle数据库到MySQL数据库迁移过程中的一大难题就是主键生成策略的替换. 如果之前的程序中使用Oracle的Sequence机制来实现主键的自增的话. MySQL中需要使用TableGenerator进行等价替换.

替换的时候,主要有三个地方需要修改:

  • 以注解方式完成hibernate映射的实体;
  • 以xml方式完成hibernate映射的实体;
  • 数据库存储过程;

注解方式完成hibernate映射的实体的修改

使用Oracle Sequence

假如你之前的程序使用的是Sequence,这里以一个名为SEQSequence为例,那么你操作id字段的代码应该长的是下面这个样子:

// 注意: 如果不指定sequenceName的话,默认为HIBERNATE_SEQUENCE,这个序列也需要在Oracle中手动建立.
@SequenceGenerator(name = "generator",sequenceName = "SEQ")
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "generator")
public Long getId() {
    return id;
}

使用MySQL表模拟Oracle Sequence

首先你需要在MySQL中建立一个表sys_sequence,表中有两个字段,一个是seq_name,代表Oracle序列的名称,另一个是current_value,代表该序列的当前值(注意: 需要将此初始值设定为Oracle数据库中对应序列的当前值.). 表的样子如下:

> select * from sys_sequence;
+--------------+------------+
| seq_name     | curr_value |
+--------------+------------+
| SEQ          |      2809  |
+--------------+------------+

. 然后在程序中如下编写:

/** * allocationSize是每次程序启动第一次插入时与之前最大值的差值. */
@Id
@TableGenerator(name = "sequence",table = "sys_sequence",pkColumnName = "seq_name",valueColumnName = "curr_value",pkColumnValue = "SEQ",allocationSize = 1)
@GeneratedValue(strategy = GenerationType.TABLE,generator = "sequence")
private Long id;

xml方式完成hibernate映射的实体的修改

使用Oracle Sequence

之前使用Sequence作为主键生成策略的时候,xml映射文件片段如下:

<id name="id">
    <generator class="sequence">
        <param name="sequence">SEQ</param>
    </generator>
</id>

使用MySQL表模拟Oracle Sequence

表的结构与前面注解方式所用的表结构相同. 这次我们在xml中使用的generator是org.hibernate.id.enhanced.TableGenerator:

<id name="id">
    <generator class="org.hibernate.id.enhanced.TableGenerator">
        <param name="table_name">sys_sequence</param>
        <param name="segment_column_name">seq_name</param>
        <param name="value_column_name">curr_value</param>
        <param name="segment_value">SEQ</param>
        <param name="increment_size">1</param>
    </generator>
</id>

存储过程的修改

存储过程中,主要涉及到Sequencenextval()等方法的替换,我们同样可以在MySQL中进行模拟.

使用Oracle Sequence

假设我们现在有一个Sequence名为SEQ,那么我们通常在存储过程中使用如下函数获得SEQ的下一个值:

SEQ.nextval

使用MySQL模拟Oracle Sequence

首先需要创建一个表格,用于存储所有序列的名称,当前值以及递增步长. 这里我们继续沿用前面所述的sys_sequence表,不过还需要为表新增一个字段increment_by,我们对照Oracle数据库的设置手动进行increment_by初值的设定.

> select * from sys_sequence;
+--------------+------------+--------------+
| seq_name     | curr_value | increment_by |
+--------------+------------+--------------+
| SEQ          |      2809  |            1 |
+--------------+------------+--------------+

然后在数据库中新增两个函数,一个是currval,用于获取模拟的Sequence的当前值:

CREATE DEFINER=`root`@`%` FUNCTION `currval`(`v_seq_name` varchar(50)) RETURNS decimal(18,0) BEGIN DECLARE v_currval DECIMAL(18);
    SET v_currval = 1;  
    SELECT curr_value INTO v_currval FROM sys_sequence WHERE seq_name = v_seq_name;  
    RETURN v_currval;  
END

另一个是nextval,用户获取模拟的Sequence的下一个值:

CREATE DEFINER=`root`@`%` FUNCTION `nextval`(`v_seq_name` varchar(50)) RETURNS decimal(18,0) BEGIN UPDATE sys_sequence SET curr_value = curr_value + increment_by WHERE seq_name = v_seq_name;  
    RETURN currval(v_seq_name);  
END

之后在需要使用Sequence的地方,使用如下语句替代即可:

nextval('SEQ')

小结

如此一来,就达到了利用MySQL的表来模拟Oracle的Sequence的目的. 以后每当有需要替换的序列,都在前面建立的sys_sequence中新增一行即可.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读