This commit is contained in:
Redkale
2016-11-25 17:20:28 +08:00
parent 34cb4f87b4
commit d5a6220b58
2 changed files with 203 additions and 36 deletions

View File

@@ -59,7 +59,7 @@
<h3><a class="anchor" href="source.html#source_datasource" target="_blank" aria-hidden="true">亮点四. DataSource</a></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redkale提供DataSource类对数据层进行操作其功能类似JPA。最大程度的简化数据层的操作免去SQL/JPQL语句的编写。同时提供过滤查询与JavaBean的结合、读写分离、数据库热切换、本地/远程部署、数据分库分表、进程间缓存自动同步等功能。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redkale提供DataSource类对数据层进行操作其功能类似JPA。最大程度的简化数据层的操作免去SQL/JPQL语句的编写。同时提供过滤查询与JavaBean的结合、读写分离、数据库热切换、本地/远程部署、数据分表分库、进程间缓存自动同步等功能。</p>
<h3><a id="redkale_code" class="anchor" href="#" aria-hidden="true"></a>Java 源码</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://github.com/redkale" target="_blank" >Github 源码 &nbsp;&nbsp; https://github.com/redkale</a><br/>

View File

@@ -43,14 +43,14 @@
<tr><td style="text-align: left;">javax.persistence.Cacheable</td><td>标记Entity类是否需要缓存与JPA用法一致</td></tr>
<tr><td style="text-align: left;">javax.persistence.Column</td><td>标记字段只使用其name()、insertable()、updatable()属性</td></tr>
<tr><td style="text-align: left;">javax.persistence.Entity</td><td>JPA的Entity类必须标记为@Entity, 而Redkale不强制要求所以该注解一般无用</td></tr>
<tr><td style="text-align: left;">javax.persistence.GeneratedValue</td><td>仅用于标记主键是否为数据库自增长,其内值的两属性废弃</td></tr>
<tr><td style="text-align: left;">javax.persistence.GenerationType</td><td>被@GeneratedValue的属性引用在Redkale内不被使用到</td></tr>
<tr><td style="text-align: left;">javax.persistence.GeneratedValue</td><td>仅用于标记主键是否为数据库自增长</td></tr>
<tr><td style="text-align: left;">javax.persistence.Id<td>标记主键字段与JPA用法一致</td></tr>
<tr><td style="text-align: left;">javax.persistence.Table<td>标记表的别名与JPA用法一致</td></tr>
<tr><td style="text-align: left;">javax.persistence.Transient<td>标记是否为表对应的字段与JPA用法一致</td></tr>
<tr><td style="text-align: center;font-size: 0.9rem;" colspan="2"><b>以下是Redkale自定义的注解</b></td></tr>
<tr><td style="text-align: left;"><b>@VirtualEntity</b></td><td>用于非数据库表对应的Entity类且仅用于开启缓存模式的DataSource</td></tr>
<tr><td style="text-align: left;"><b>@DistributeGenerator</b></td><td>标记主键是否采用分布式自增长策略,不能与@GeneratedValue同用</td></tr>
<tr><td style="text-align: left;"><b>@DistributeTable</b></td><td>标记表进行分表分库存储, 与DistributeTableStrategy接口结合使用</td></tr>
<tr><td style="text-align: left;"><b>@FilterColumn</b></td><td>用于FilterBean过滤类的字段设置</td></tr>
<tr><td style="text-align: left;"><b>@FilterJoinColumn</b></td><td>用于FilterBean过滤类的关联表字段设置</td></tr>
<tr><td style="text-align: left;"><b>@FilterGroup</b></td><td>用于FilterBean过滤类的过滤条件分组设置</td></tr>
@@ -64,7 +64,7 @@
<tr><td style="text-align: left;">insert</td><td>插入数据</td></tr>
<tr><td style="text-align: left;">delete</td><td>删除数据</td></tr>
<tr><td style="text-align: left;">update</td><td>更新数据</td></tr>
<tr><td style="text-align: left;">updateColumnXXX</td><td>更新数据的部分字段</td></tr>
<tr><td style="text-align: left;">updateColumn</td><td>更新数据的部分字段</td></tr>
<tr><td style="text-align: left;">getNumberResult</td><td>统计查询,用于查询字段的总和、最大值、平均值等数据</td></tr>
<tr><td style="text-align: left;">queryColumnXXX<td>单个字段数据查询和字段的统计查询</td></tr>
<tr><td style="text-align: left;">find<td>查找单个对象</td></tr>
@@ -76,7 +76,7 @@
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以上接口除了directXXX其他都有等同的异步接口。insert、delete、update接口与JPA同名接口用法一样。DataSource提供了丰富的查询接口且有独特的翻页查询功能。每以系列的方法主要重载三类 单个字段过滤、FilterBean过滤和FilterNode过滤。
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<b>过滤条件</b></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FilterBean、FilterNode对象用于构造过滤条件。FilterBean可以转化为FilterNode。FilterBean主要用于接收外界构建的过滤条件而FilterNode为了构建内部的过滤条件且降低过滤条件变化的耦合性。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FilterBean、FilterNode对象用于构造过滤条件。FilterBean可以转化为FilterNode。FilterBean主要用于接收外界构建的过滤条件而FilterNode为了构建内部的过滤条件且降低过滤条件变化的耦合性FilterNode中name值以#开头的视为虚拟字段不会构建成过滤条件仅供分布分库的DistributeTableStrategy策略使用</p>
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserBean</span> <span class="kd">implements</span> <span class="n">FilterBean</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">;</span>
@@ -144,6 +144,168 @@
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上@FilterGroup 的value 必须是[OR]或者[AND]开头,没有标记@FilterGroup的字段等价于标记了@FilterGroup(value = "[AND]")。[AND]、[OR]后面的字符串为GROUP_NAME默认的GROUP_NAME为空字符串。如上"[OR]a"可以直接使用"[OR]",有多个[OR]或者[AND]则需要加上不同的NAME。</p>
<p id="source_distribute">&nbsp;&nbsp;&nbsp;&nbsp;<b>分表分库</b></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSource提供了单个实体类对应多个数据库表的功能通常流水型的数据量比较大单个数据库无法存储DataSource提供了简单的分表操作同时在接口设计上尽量减少单表操作与分表操作的差异。分表分库只需在实体类上注解@DistributeTable并实现DistributeTableStrategy分表策略即可。</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">DistributeTableStrategy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">{</span>
<span class="cm">/**</span>
<span class="cm"> * 获取对象的表名</span>
<span class="cm"> * 查询单个对象时调用本方法获取表名</span>
<span class="cm"> *</span>
<span class="cm"> * @param table 模板表的表名</span>
<span class="cm"> * @param primary 记录主键</span>
<span class="cm"> *</span>
<span class="cm"> * @return</span>
<span class="cm"> */</span>
<span class="k">default</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="n">Serializable</span> <span class="n">primary</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
<span class="o">}</span>
<span class="cm">/**</span>
<span class="cm"> * 获取对象的表名</span>
<span class="cm"> * 查询、修改、删除对象时调用本方法获取表名</span>
<span class="cm"> * 注意: 需保证FilterNode过滤的结果集合必须在一个数据库表中</span>
<span class="cm"> *</span>
<span class="cm"> * @param table 模板表的表名</span>
<span class="cm"> * @param node 过滤条件</span>
<span class="cm"> *</span>
<span class="cm"> * @return</span>
<span class="cm"> */</span>
<span class="k">default</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="n">FilterNode</span> <span class="n">node</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
<span class="o">}</span>
<span class="cm">/**</span>
<span class="cm"> * 获取对象的表名</span>
<span class="cm"> * 新增对象或更新单个对象时调用本方法获取表名</span>
<span class="cm"> *</span>
<span class="cm"> * @param table 模板表的表名</span>
<span class="cm"> * @param bean 实体对象</span>
<span class="cm"> *</span>
<span class="cm"> * @return</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="n">T</span> <span class="n">bean</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DistributeTableStrategy分表策略需要实现三个接口除了第三个必须实现其他两个是可选的因第三个是新增时需要用到不实现则不会创建表而模板表由实体类的@Table注解提供。Redkale默认实现的MySQL数据库的拷贝表结构语句其他数据库类型需要通过指定<a href="#source_confxml">persistence.xml</a> 中的 <b>javax.persistence.tablenotexist.sqlstates</b><b>javax.persistence.tablecopy.sqltemplate</b> 来配置。</p>
<div class="highlight"><pre><span></span><span class="nd">@DistributeTable</span><span class="o">(</span><span class="n">strategy</span> <span class="o">=</span> <span class="n">LoginRecord</span><span class="o">.</span><span class="na">TableStrategy</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">LoginRecord</span> <span class="kd">extends</span> <span class="n">BaseEntity</span> <span class="o">{</span>
<span class="nd">@Id</span>
<span class="nd">@GeneratedValue</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;UUID&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">seqid</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//UUID</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">updatable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;C端用户ID&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="kt">long</span> <span class="n">userid</span><span class="o">;</span> <span class="c1">//C端用户ID</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">updatable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;登录网络类型; wifi/4g/3g&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">netmode</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//登录网络类型; wifi/4g/3g</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">updatable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;APP版本信息&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">appversion</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//APP版本信息</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">updatable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;APP操作系统信息&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">appos</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//APP操作系统信息</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">updatable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;登录时客户端信息&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">loginagent</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//登录时客户端信息</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">updatable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;登录时的IP&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">loginaddr</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//登录时的IP</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">updatable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;创建时间&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="kt">long</span> <span class="n">createtime</span><span class="o">;</span> <span class="c1">//创建时间</span>
<span class="cm">/** 以下省略getter setter方法 */</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">TableStrategy</span> <span class="kd">implements</span> <span class="n">DistributeTableStrategy</span><span class="o">&lt;</span><span class="n">LoginRecord</span><span class="o">&gt;</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">dayformat</span> <span class="o">=</span> <span class="s">&quot;%1$tY%1$tm%1$td&quot;</span><span class="o">;</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">yearformat</span> <span class="o">=</span> <span class="s">&quot;%1$tY&quot;</span><span class="o">;</span>
<span class="c1">//过滤查询时调用本方法</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="n">FilterNode</span> <span class="n">node</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Serializable</span> <span class="n">day</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="na">findValue</span><span class="o">(</span><span class="s">&quot;#day&quot;</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">day</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="n">getTable</span><span class="o">(</span><span class="n">table</span><span class="o">,</span> <span class="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">day</span><span class="o">,</span> <span class="mi">0</span><span class="n">L</span><span class="o">);</span> <span class="c1">//存在#day参数则直接使用day值</span>
<span class="n">Serializable</span> <span class="n">time</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="na">findValue</span><span class="o">(</span><span class="s">&quot;#createtime&quot;</span><span class="o">);</span> <span class="c1">//存在createtime则使用最小时间且createtime的范围必须在一天内因为本表以天为单位建表</span>
<span class="k">return</span> <span class="n">getTable</span><span class="o">(</span><span class="n">table</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="o">(</span><span class="n">time</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="mi">0</span><span class="n">L</span> <span class="o">:</span> <span class="o">(</span><span class="n">time</span> <span class="k">instanceof</span> <span class="n">Range</span> <span class="o">?</span> <span class="o">((</span><span class="n">Range</span><span class="o">.</span><span class="na">LongRange</span><span class="o">)</span> <span class="n">time</span><span class="o">).</span><span class="na">getMin</span><span class="o">()</span> <span class="o">:</span> <span class="o">(</span><span class="n">Long</span><span class="o">)</span> <span class="n">time</span><span class="o">)));</span>
<span class="o">}</span>
<span class="c1">//创建或单个查询时调用本方法</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="n">LoginRecord</span> <span class="n">bean</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">getTable</span><span class="o">(</span><span class="n">table</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="n">bean</span><span class="o">.</span><span class="na">getCreatetime</span><span class="o">());</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="kt">int</span> <span class="n">day</span><span class="o">,</span> <span class="kt">long</span> <span class="n">createtime</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">pos</span> <span class="o">=</span> <span class="n">table</span><span class="o">.</span><span class="na">indexOf</span><span class="o">(</span><span class="sc">&#39;.&#39;</span><span class="o">);</span>
<span class="n">String</span> <span class="n">year</span> <span class="o">=</span> <span class="o">(</span><span class="n">day</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="s">&quot;&quot;</span> <span class="o">+</span> <span class="n">day</span> <span class="o">/</span> <span class="mi">10000</span> <span class="o">:</span> <span class="n">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="n">yearformat</span><span class="o">,</span> <span class="n">createtime</span><span class="o">));</span>
<span class="k">return</span> <span class="s">&quot;platf_login_&quot;</span> <span class="o">+</span> <span class="n">year</span> <span class="o">+</span> <span class="s">&quot;.&quot;</span> <span class="o">+</span> <span class="n">table</span><span class="o">.</span><span class="na">substring</span><span class="o">(</span><span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="o">)</span> <span class="o">+</span> <span class="s">&quot;_&quot;</span> <span class="o">+</span> <span class="o">(</span><span class="n">day</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">day</span> <span class="o">:</span> <span class="n">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="n">dayformat</span><span class="o">,</span> <span class="n">createtime</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以上范例是用户登陆记录的分表分库策略一年一个库一个库中365张表每天一个表。由于分表是根据记录的创建时间作为策略分表因此策略接口中的public String getTable(String table, Serializable primary) 方法不能实现因为根据主键id无法确定到数据库表。</p>
<div class="highlight"><pre><span></span><span class="nd">@DistributeTable</span><span class="o">(</span><span class="n">strategy</span> <span class="o">=</span> <span class="n">UserDetail</span><span class="o">.</span><span class="na">TableStrategy</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserDetail</span> <span class="kd">extends</span> <span class="n">BaseEntity</span> <span class="o">{</span>
<span class="nd">@Id</span>
<span class="kd">private</span> <span class="kt">long</span> <span class="n">userid</span><span class="o">;</span> <span class="c1">//用户ID</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">length</span> <span class="o">=</span> <span class="mi">64</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;用户昵称&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">username</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//用户昵称</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">length</span> <span class="o">=</span> <span class="mi">32</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;手机号码&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">mobile</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//手机号码</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">length</span> <span class="o">=</span> <span class="mi">64</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;密码&quot;</span><span class="o">)</span>
<span class="nd">@ConvertColumn</span><span class="o">(</span><span class="n">ignore</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="n">ConvertType</span><span class="o">.</span><span class="na">ALL</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">password</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//密码</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">length</span> <span class="o">=</span> <span class="mi">128</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;备注&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">remark</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//备注</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">updatable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;创建时间&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="kt">long</span> <span class="n">createtime</span><span class="o">;</span> <span class="c1">//创建时间</span>
<span class="cm">/** 以下省略getter setter方法 */</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">TableStrategy</span> <span class="kd">implements</span> <span class="n">DistributeTableStrategy</span><span class="o">&lt;</span><span class="n">UserDetail</span><span class="o">&gt;</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="n">UserDetail</span> <span class="n">bean</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">getTable</span><span class="o">(</span><span class="n">table</span><span class="o">,</span> <span class="n">bean</span><span class="o">.</span><span class="na">getUserid</span><span class="o">());</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="n">FilterNode</span> <span class="n">node</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Serializable</span> <span class="n">id</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="na">findValue</span><span class="o">(</span><span class="s">&quot;userid&quot;</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">id</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">getTable</span><span class="o">(</span><span class="n">table</span><span class="o">,</span> <span class="n">id</span><span class="o">);</span>
<span class="k">return</span> <span class="n">getHashTable</span><span class="o">(</span><span class="n">table</span><span class="o">,</span> <span class="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">node</span><span class="o">.</span><span class="na">findValue</span><span class="o">(</span><span class="s">&quot;#hash&quot;</span><span class="o">));</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="n">Serializable</span> <span class="n">userid</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">getHashTable</span><span class="o">(</span><span class="n">table</span><span class="o">,</span> <span class="o">(</span><span class="kt">int</span><span class="o">)</span> <span class="o">(((</span><span class="n">Long</span><span class="o">)</span> <span class="n">userid</span><span class="o">)</span> <span class="o">%</span> <span class="mi">100</span><span class="o">));</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="n">String</span> <span class="nf">getHashTable</span><span class="o">(</span><span class="n">String</span> <span class="n">table</span><span class="o">,</span> <span class="kt">int</span> <span class="n">hash</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">pos</span> <span class="o">=</span> <span class="n">table</span><span class="o">.</span><span class="na">indexOf</span><span class="o">(</span><span class="sc">&#39;.&#39;</span><span class="o">);</span>
<span class="k">return</span> <span class="s">&quot;platf_user.&quot;</span> <span class="o">+</span> <span class="n">table</span><span class="o">.</span><span class="na">substring</span><span class="o">(</span><span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="o">)</span> <span class="o">+</span> <span class="s">&quot;_&quot;</span> <span class="o">+</span> <span class="o">(</span><span class="n">hash</span> <span class="o">&gt;</span> <span class="mi">9</span> <span class="o">?</span> <span class="n">hash</span> <span class="o">:</span> <span class="o">(</span><span class="s">&quot;0&quot;</span> <span class="o">+</span> <span class="n">hash</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h3><a id="source_cachesource" class="anchor" href="#" aria-hidden="true"></a>CacheSource 入门</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CacheSource同Memcached类似像一个带有过期功能地Map容器存放key-value数据。常见的使用场景就是存放HTTP的Session信息。Redkale把用户会话信息数据当做业务数据处理而不是接入层的数据。WebSocket的连接态数据也是用CacheSource存储。key为WebSocket的groupidvalue为WebSocket服务端节点的IP地址列表。</p>
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserService</span> <span class="kd">implements</span> <span class="n">Service</span> <span class="o">{</span>
@@ -178,49 +340,54 @@
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以上是个简单的范例用于用户模块存放sessionid。</p>
<h3><a id="source_confxml" href="#" aria-hidden="true"></a>persistence.xml 配置说明</h3>
<div class="highlight"><pre><span class="c">&lt;!-- 其配置算是标准的JPA配置文件的缩略版 --&gt;</span>
<span class="nt">&lt;persistence&gt;</span>
<div class="highlight"><pre><span></span><span class="c">&lt;!-- 其配置算是标准的JPA配置文件的缩略版 --&gt;</span>
<span class="p">&lt;</span><span class="nt">persistence</span><span class="p">&gt;</span>
<span class="c">&lt;!-- 系统基本库 --&gt;</span>
<span class="nt">&lt;persistence-unit</span> <span class="na">name=</span><span class="s">&quot;demouser&quot;</span><span class="nt">&gt;</span>
<span class="p">&lt;</span><span class="nt">persistence-unit</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;demouser&quot;</span><span class="p">&gt;</span>
<span class="c">&lt;!-- 为NONE表示不启动缓存@Cacheable 失效; 非NONE值(通常用ALL)表示开启缓存。 --&gt;</span>
<span class="nt">&lt;shared-cache-mode&gt;</span>NONE<span class="nt">&lt;/shared-cache-mode&gt;</span>
<span class="nt">&lt;properties&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;javax.persistence.jdbc.url&quot;</span> <span class="na">value=</span><span class="s">&quot;jdbc:mysql://127.0.0.1:3306/dbuser?characterEncoding=utf8&quot;</span><span class="nt">/&gt;</span>
<span class="p">&lt;</span><span class="nt">shared-cache-mode</span><span class="p">&gt;</span>NONE<span class="p">&lt;/</span><span class="nt">shared-cache-mode</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">properties</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.jdbc.url&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;jdbc:mysql://127.0.0.1:3306/dbuser?characterEncoding=utf8&quot;</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> javax.persistence.jdbc.driver在JPA的值是JDBC驱动Redkale有所不同值应该是javax.sql.DataSource的子类。 </span>
<span class="c"> 为了兼容用户习惯Redkale内置常见JDBC驱动到javax.sql.DataSource的映射关系</span>
<span class="c"> com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</span>
<span class="c"> org.mariadb.jdbc.Driver —————— org.mariadb.jdbc.MySQLDataSource</span>
<span class="c"> org.postgresql.Driver —————— org.postgresql.ds.PGConnectionPoolDataSource</span>
<span class="c"> com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</span>
<span class="c"> oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource</span>
<span class="c"> com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource</span>
<span class="c"> 因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</span>
<span class="c"> --&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;javax.persistence.jdbc.driver&quot;</span> <span class="na">value=</span><span class="s">&quot;com.mysql.jdbc.Driver&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;javax.persistence.jdbc.user&quot;</span> <span class="na">value=</span><span class="s">&quot;root&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;javax.persistence.jdbc.password&quot;</span> <span class="na">value=</span><span class="s">&quot;123456&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 最大连接数默认值CPU数*16</span>
<span class="c"> &lt;property name=&quot;javax.persistence.connections.limit&quot; value=&quot;32&quot;/&gt;</span>
<span class="c"> --&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 包含的SQL模板相当于反向LIKE不同的JDBC驱动的SQL语句不一样Redkale内置了MySQL、Oracle、Sqlserver的语句</span>
<span class="c"> &lt;property name=&quot;javax.persistence.contain.sqltemplate&quot; value=&quot;LOCATE(${keystr}, ${column}) &gt; 0&quot;/&gt;</span>
<span class="c"> &lt;property name=&quot;javax.persistence.notcontain.sqltemplate&quot; value=&quot;LOCATE(${keystr}, ${column}) = 0&quot;/&gt;</span>
<span class="c"> --&gt;</span>
<span class="nt">&lt;/properties&gt;</span>
<span class="nt">&lt;/persistence-unit&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.jdbc.driver&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;com.mysql.jdbc.Driver&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.jdbc.user&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;root&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.jdbc.password&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;123456&quot;</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- 最大连接数默认值CPU数*16 --&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.connections.limit&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;32&quot;</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- 包含的SQL模板相当于反向LIKE不同的JDBC驱动的SQL语句不一样Redkale内置了MySQL的语句 --&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.contain.sqltemplate&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;LOCATE(${keystr}, ${column}) &gt; 0&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.notcontain.sqltemplate&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;LOCATE(${keystr}, ${column}) = 0&quot;</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- 复制表结构的SQL模板Redkale内置了MySQL的语句 --&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.tablenotexist.sqlstates&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;42000;42S02&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.tablecopy.sqltemplate&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;CREATE TABLE ${newtable} LIKE ${oldtable}&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">properties</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">persistence-unit</span><span class="p">&gt;</span>
<span class="c">&lt;!-- IM消息库 --&gt;</span>
<span class="nt">&lt;persistence-unit</span> <span class="na">name=</span><span class="s">&quot;demoim&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;shared-cache-mode&gt;</span>NONE<span class="nt">&lt;/shared-cache-mode&gt;</span>
<span class="nt">&lt;properties&gt;</span>
<span class="p">&lt;</span><span class="nt">persistence-unit</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;demoim&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">shared-cache-mode</span><span class="p">&gt;</span>NONE<span class="p">&lt;/</span><span class="nt">shared-cache-mode</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">properties</span><span class="p">&gt;</span>
<span class="c">&lt;!-- jdbc:mysql://127.0.0.1:3306/dbim?autoReconnect=true&amp;amp;autoReconnectForPools=true&amp;amp;characterEncoding=utf8 --&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;javax.persistence.jdbc.url&quot;</span> <span class="na">value=</span><span class="s">&quot;jdbc:mysql://127.0.0.1:3306/dbim?characterEncoding=utf8&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;javax.persistence.jdbc.driver&quot;</span> <span class="na">value=</span><span class="s">&quot;com.mysql.jdbc.Driver&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;javax.persistence.jdbc.user&quot;</span> <span class="na">value=</span><span class="s">&quot;root&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;javax.persistence.jdbc.password&quot;</span> <span class="na">value=</span><span class="s">&quot;123456&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/properties&gt;</span>
<span class="nt">&lt;/persistence-unit&gt;</span>
<span class="nt">&lt;/persistence&gt;</span></pre></div>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.jdbc.url&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;jdbc:mysql://127.0.0.1:3306/dbim?characterEncoding=utf8&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.jdbc.driver&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;com.mysql.jdbc.Driver&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.jdbc.user&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;root&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;javax.persistence.jdbc.password&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;123456&quot;</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">properties</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">persistence-unit</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">persistence</span><span class="p">&gt;</span>
</pre></div>
<footer class="site-footer">
<span class="site-footer-owner">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;欢迎加入Redkale QQ群: 527523235</span>