From 133b8292571fc7831313bca7ed91505327552fa0 Mon Sep 17 00:00:00 2001 From: Redkale <22250530@qq.com> Date: Thu, 2 Mar 2017 16:04:11 +0800 Subject: [PATCH] --- source.html | 85 ++++++----------------------------------------------- 1 file changed, 9 insertions(+), 76 deletions(-) diff --git a/source.html b/source.html index c62269357..b70d68bdc 100644 --- a/source.html +++ b/source.html @@ -158,9 +158,7 @@ * * @return */ - default String getTable(String table, Serializable primary) { - return null; - } + public String getTable(String table, Serializable primary); /** * 获取对象的表名 @@ -172,9 +170,7 @@ * * @return */ - default String getTable(String table, FilterNode node) { - return null; - } + public String getTable(String table, FilterNode node); /** * 获取对象的表名 @@ -189,70 +185,7 @@ } -

        DistributeTableStrategy分表策略需要实现三个接口,除了第三个必须实现,其他两个是可选的,因第三个是新增时需要用到,不实现则不会创建表,而模板表由实体类的@Table注解提供。Redkale默认实现的MySQL数据库的拷贝表结构语句,其他数据库类型需要通过指定persistence.xml 中的 javax.persistence.tablenotexist.sqlstatesjavax.persistence.tablecopy.sqltemplate 来配置。

- -
@DistributeTable(strategy = LoginRecord.TableStrategy.class)
-public class LoginRecord extends BaseEntity {
-
-    @Id
-    @GeneratedValue
-    @Column(comment = "UUID")
-    private String loginid = ""; //UUID
-
-    @Column(updatable = false, comment = "C端用户ID")
-    private long userid; //C端用户ID
-
-    @Column(updatable = false, comment = "登录网络类型; wifi/4g/3g")
-    private String netmode = ""; //登录网络类型; wifi/4g/3g
-
-    @Column(updatable = false, comment = "APP版本信息")
-    private String appversion = ""; //APP版本信息
-
-    @Column(updatable = false, comment = "APP操作系统信息")
-    private String appos = ""; //APP操作系统信息
-
-    @Column(updatable = false, comment = "登录时客户端信息")
-    private String loginagent = ""; //登录时客户端信息
-
-    @Column(updatable = false, comment = "登录时的IP")
-    private String loginaddr = ""; //登录时的IP
-
-    @Column(updatable = false, comment = "创建时间")
-    private long createtime; //创建时间
-
-    /** 以下省略getter setter方法 */
- 
-
-    public static class TableStrategy implements DistributeTableStrategy<LoginRecord> {
-
-        private static final String dayformat = "%1$tY%1$tm%1$td";
-
-        private static final String yearformat = "%1$tY";
-
-        //过滤查询时调用本方法
-        @Override
-        public String getTable(String table, FilterNode node) {
-            Serializable day = node.findValue("#day");
-            if (day != null) getTable(table, (Integer) day, 0L); //存在#day参数则直接使用day值
-            Serializable time = node.findValue("#createtime");  //存在createtime则使用最小时间,且createtime的范围必须在一天内,因为本表以天为单位建表
-            return getTable(table, 0, (time == null ? 0L : (time instanceof Range ? ((Range.LongRange) time).getMin() : (Long) time)));
-        }
-
-        //创建或单个查询时调用本方法
-        @Override
-        public String getTable(String table, LoginRecord bean) {
-            return getTable(table, 0, bean.getCreatetime());
-        }
-
-        private String getTable(String table, int day, long createtime) {
-            int pos = table.indexOf('.');
-            String year = (day > 0 ? "" + day / 10000 : String.format(yearformat, createtime));
-            return "platf_login_" + year + "." + table.substring(pos + 1) + "_" + (day > 0 ? day : String.format(dayformat, createtime));
-        }
-    }
-}
-                
-

         以上范例是用户登陆记录的分表分库策略,一年一个库,一个库中365张表,每天一个表。由于分表是根据记录的创建时间作为策略分表,因此策略接口中的public String getTable(String table, Serializable primary) 方法无法实现,根据主键id无法判断出数据所在的数据库表。若有根据ID获取单条记录的需求,则需要变更loginid的生成规则,可以改成UUID+createtime,如下:

+

        DistributeTableStrategy分表策略需要实现三个接口,模板表由实体类的@Table注解提供。Redkale默认实现的MySQL数据库的拷贝表结构语句,其他数据库类型需要通过指定persistence.xml 中的 javax.persistence.tablenotexist.sqlstatesjavax.persistence.tablecopy.sqltemplate 来配置。

@DistributeTable(strategy = LoginRecord.TableStrategy.class)
 public class LoginRecord extends BaseEntity {
 
@@ -333,14 +266,13 @@
     }
 }
                 
-

         如上范例,若需要分表策略的三个接口均得到实现,需要对主键ID的生成规则进行一定的设计。并不是所有的数据表都需要进行全量查询或单个记录查询,开发人员可根据使用场景来设计分表策略和主键生成规则。事实上用户登录记录很少场景需要查询单个记录的, 但是常见的场景是查询单个用户的登录列表。上面的范例无法满足查询单个用户的登录信息需求,而分表策略又只能根据一种规则生成,因此需要按用户维度存在另外一张表中。

+

         如上范例,用户登陆记录的分表分库策略为一年一个库,一个库中365张表,每天一个表。为了分表策略的三个接口均得到实现,需要对主键ID的生成规则进行一定的设计。常见的场景是查询单个用户的登录列表。上面的范例就无法满足查询单个用户的登录信息需求,而分表策略又只能根据一种规则生成,因此需要按用户维度存在另外一张表中。

@DistributeTable(strategy = LoginUserRecord.TableStrategy.class)
 public class LoginUserRecord extends BaseEntity {
 
     @Id
-    @GeneratedValue
-    @Column(comment = "UUID")
-    private String seqid = ""; //UUID
+    @Column(comment = "记录ID; 值=userid+'-'+UUID")
+    private String seqid = ""; //记录ID; 值=userid+'-'+UUID
 
     @Column(updatable = false, comment = "C端用户ID")
     private long userid; //C端用户ID
@@ -368,8 +300,9 @@
         }
 
         @Override
-        public String getTable(String table, Serializable userid) {
-            return getHashTable(table, (int) (((Long) userid) % 100));
+        public String getTable(String table, Serializable primary) {
+            String id = (String) primary;
+            return getHashTable(table, (int) (Long.parseLong(id.substring(0, id.indexOf('-'))) % 100));
         }
 
         private String getHashTable(String table, int hash) {