<h2 dir="auto">Bug Report</h2>
<h3 dir="auto">Development environment</h3>
<p dir="auto">Spring Boot: 2.5.4<br>
MyBatis Spring Boot Starter: 2.2.0<br>
ShardingSphere JDBC: 5.0.0-beta<br>
MySQL: 8.0.23</p>
<h3 dir="auto">Which version of ShardingSphere did you use?</h3>
<p dir="auto">5.0.0-beta</p>
<h3 dir="auto">Which project did you use? ShardingSphere-JDBC or ShardingSphere-Proxy?</h3>
<p dir="auto">shardingsphere-jdbc-core</p>
<h3 dir="auto">Expected behavior</h3>
<p dir="auto">Throw an exception.<br>
The username field is unique, an exception should be thrown when adding duplicates. It is normal when not using ShardingSphere.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="org.springframework.dao.DuplicateKeyException: 
### Error updating database.  Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'suikenung' for key 'user.uk_username'
### The error may exist in file [D:\Software\JetBrains\Projects\Java\sugus\sugus-system\target\classes\mapper\UserMapper.xml]
### The error may involve com.lrq.sugus.system.mapper.UserMapper.insert-Inline
### The error occurred while setting parameters
### SQL: insert into `user`          ( username,                                           `password`,                                           enabled,                                           full_name,                                           email,                                           mobile,                                           sex )           values ( ?,                                           ?,                                           ?,                                           ?,                                           ?,                                           ?,                                           ? )
### Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'suikenung' for key 'user.uk_username'
; Duplicate entry 'suikenung' for key 'user.uk_username'; nested exception is java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'suikenung' for key 'user.uk_username'"><pre class="notranslate"><code class="notranslate">org.springframework.dao.DuplicateKeyException: 
### Error updating database.  Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'suikenung' for key 'user.uk_username'
### The error may exist in file [D:\Software\JetBrains\Projects\Java\sugus\sugus-system\target\classes\mapper\UserMapper.xml]
### The error may involve com.lrq.sugus.system.mapper.UserMapper.insert-Inline
### The error occurred while setting parameters
### SQL: insert into `user`          ( username,                                           `password`,                                           enabled,                                           full_name,                                           email,                                           mobile,                                           sex )           values ( ?,                                           ?,                                           ?,                                           ?,                                           ?,                                           ?,                                           ? )
### Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'suikenung' for key 'user.uk_username'
; Duplicate entry 'suikenung' for key 'user.uk_username'; nested exception is java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'suikenung' for key 'user.uk_username'
</code></pre></div>
<h3 dir="auto">Actual behavior</h3>
<p dir="auto">When using ShardingSphere, nothing happened. And no exception is thrown.</p>
<p dir="auto">Adding dependent antlr4-runtime has no effect.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;dependency&gt;
    &lt;groupId&gt;org.antlr&lt;/groupId&gt;
    &lt;artifactId&gt;antlr4-runtime&lt;/artifactId&gt;
    &lt;version&gt;4.7.2&lt;/version&gt;
&lt;/dependency&gt;"><pre class="notranslate"><code class="notranslate">&lt;dependency&gt;
    &lt;groupId&gt;org.antlr&lt;/groupId&gt;
    &lt;artifactId&gt;antlr4-runtime&lt;/artifactId&gt;
    &lt;version&gt;4.7.2&lt;/version&gt;
&lt;/dependency&gt;
</code></pre></div>
<h3 dir="auto">Reason analyze (If you can)</h3>
<h3 dir="auto">Steps to reproduce the behavior, such as: SQL to execute, sharding rule configuration, when exception occur etc.</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="CREATE TABLE `user`  (
  ...
  UNIQUE INDEX `uk_username`(`username`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;"><pre class="notranslate"><code class="notranslate">CREATE TABLE `user`  (
  ...
  UNIQUE INDEX `uk_username`(`username`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;
</code></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;insert id=&quot;insert&quot; keyProperty=&quot;id&quot; parameterType=&quot;com.lrq.sugus.system.dataobject.UserDO&quot; useGeneratedKeys=&quot;true&quot;&gt;
	insert into `user` (username) values (#{username})
&lt;/insert&gt;"><pre class="notranslate"><code class="notranslate">&lt;insert id="insert" keyProperty="id" parameterType="com.lrq.sugus.system.dataobject.UserDO" useGeneratedKeys="true"&gt;
	insert into `user` (username) values (#{username})
&lt;/insert&gt;
</code></pre></div>
<h3 dir="auto">Example codes for reproduce this issue (such as a github link).</h3>
<p dir="auto">Hi,</p>
<p dir="auto">If you're interested in this one, please comment below so I can assign it to u. :)</p>
<h3 dir="auto">Background</h3>
<p dir="auto"><code class="notranslate">OptimizeContextFactory</code> is created in the constructor of <code class="notranslate">StandardMetaDataContexts</code> with <code class="notranslate">metaDataMap</code>.<br>
If you dive into the constructor of <code class="notranslate">OptimizeContextFactory</code> and <code class="notranslate">MetaDataContextsBuilder</code>,  you will find both handlings of them need loading table metadata. Therefore, this issue is to reduce the unnecessary and duplicated table metadata loading.</p>
<h3 dir="auto">Expected result</h3>
<ul dir="auto">
<li>Create <code class="notranslate">OptimizeContextFactory</code> in <code class="notranslate">MetaDataContextsBuilder</code></li>
<li>Share the table metadata loading between <code class="notranslate">OptimizeContextFactory</code> and <code class="notranslate">Map&lt;String, ShardingSphereMetaData&gt;</code> of <code class="notranslate">StandardMetaDataContexts</code></li>
</ul>
<h3 dir="auto">How</h3>
<ul dir="auto">
<li>The entrance is <code class="notranslate">buildSchema()</code> of <code class="notranslate">MetaDataContextsBuilder</code></li>
<li>Change the result of <code class="notranslate">SchemaBuilder.build()</code> to <code class="notranslate">Map&lt;ActualTableMetadata, LogicTableMetadata&gt;</code><br>
In <code class="notranslate">SchemaBuilder</code>,<br>
<code class="notranslate">addRuleConfiguredTables</code> returns <code class="notranslate">logicTableMetadata</code>. On the other hand <code class="notranslate">appendRemainTables(materials, result);</code> returns <code class="notranslate">actualTableMetadata</code>. So we need to call <code class="notranslate">load()</code> and <code class="notranslate">decorate()</code> of <code class="notranslate">TableMetaDataBuilder</code> respectively to get the acutal and logic ones.</li>
<li>Assemble <code class="notranslate">ShardingSphereSchema</code> using the list of logic table metadata</li>
<li>Create <code class="notranslate">OptimizeContextFactory</code> by the list of actual table metadata</li>
<li>Remove the deprecated constructors of <code class="notranslate">FederateSchemaMetadata</code> and <code class="notranslate">FederateTableMetadata</code></li>
</ul>