13.3 Sharding Data Source for Transparent Access to Sharded Databases
Oracle Database Release 21c introduced a new JDBC data source that enables Java connectivity to a sharded database without the need for an application to furnish a sharding key.
If you use the sharding data source, then you do not have to identify and build the sharding key and the super sharding key to establish a connection to the sharded database, as discussed in the earlier How to Checkout Connections from a Pool with a Sharding Key section. The sharding data source also eliminates the need to maintain a separate data source for multishard queries.
This data source scales out to sharded databases transparently if you set the connection property oracle.jdbc.useShardingDriverConnection
to true
.
The following code snippet shows how to use the sharded data source:
Example 13-2 Using the Sharded Data Source
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import oracle.jdbc.internal.OracleConnection;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
public class ShardingDataSourceUCP {
public static void main(String[] args) throws SQLException {
ShardingDataSourceUCP sample = new ShardingDataSourceUCP();
DataSource ucpDataSource = sample.getDataSource();
// Get the details of following customers
int[] customerIds = new int[] {
100,
101,
102,
103,
104,
105
};
for (int id: customerIds) {
try (Connection conn = ucpDataSource.getConnection()) {
sample.displayCustomerDetails(conn, id);
System.out.println(((OracleConnection) conn).getPercentageQueryExecutionOnDirectShard());
}
}
}
private void displayCustomerDetails(Connection conn, int id) throws SQLException {
try (PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM CUSTOMER where ID = ?")) {
pstmt.setInt(1, id);
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
// Print the customer details
}
}
}
}
private DataSource getDataSource() throws SQLException {
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
pds.setURL("<gsmURL>");
pds.setUser("<userName>");
pds.setPassword("<password>");
pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
Properties prop = new Properties();
// Connection property to enable sharding datasource feature, when this property
// is set you don't need to pass sharding key to UCP pool while borrowing the connection
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_USE_SHARDING_DRIVER_CONNECTION, "true");
pds.setConnectionProperties(prop);
return pds;
}
}
13.3.1 Support for Single Shard Transactions
The sharding data source enables you to limit your transactions to one single shard.
To enable single shard transaction support, you must set CONNECTION_PROPERTY_ALLOW_SINGLE_SHARD_TRANSACTION_SUPPORT
. If this property is not set, then by default, all the transactions are started on the Shard Catalog. If you set the value of this property to true
, then you must ensure that all the transactions span over a single shard only.
Example 13-3 Enabling Single Shard Transactions
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import oracle.jdbc.internal.OracleConnection;
import oracle.jdbc.pool.OracleDataSource;
public class SingleShardTransactionUCP {
public static void main(String[] args) throws SQLException {
SingleShardTransactionUCP sample = new SingleShardTransactionUCP();
DataSource ucpDS = sample.getDataSource();
// Insert and update the details of following customers in a single transaction
int[] customerIds = new int[] {
100,
101,
102,
103,
104,
105
};
for (int id: customerIds) {
try (Connection conn = ucpDS.getConnection()) {
conn.setAutoCommit(false);
sample.insertCustomerDetails(conn, id);
sample.displayCustomerDetails(conn, id);
sample.updateCustomerDetails(conn, id);
sample.displayCustomerDetails(conn, id);
conn.commit();
System.out.println(((OracleConnection) conn).getPercentageQueryExecutionOnDirectShard());
}
}
}
private void insertCustomerDetails(Connection conn, int id) throws SQLException {
String sql = "insert into CUSTOMER values(?, ?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, id);
ps.setString(2, name);
ps.setString(3, email);
ps.setString(4, phoneNumber);
ps.executeUpdate();
}
}
private void updateCustomerDetails(Connection conn, int id) throws SQLException {
String sql = "UPDATE CUSTOMER SET name = ?, email = ?, phoneNumber = ? WHERE customerId = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, name);
ps.setString(2, email);
ps.setString(3, phoneNumber);
ps.setInt(4, id);
ps.executeUpdate();
}
}
private void displayCustomerDetails(Connection conn, int id) throws SQLException {
try (PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM CUSTOMER where ID = ?")) {
pstmt.setInt(1, id);
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
//Print the customer details
}
}
}
}
private DataSource getDataSource() throws SQLException {
OracleDataSource ds = new OracleDataSource();
ds.setURL( < gsmURL > );
ds.setUser( < userName > );
ds.setPassword( < password > );
Properties prop = new Properties();
//Connection property to enable sharding datasource feature
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_USE_SHARDING_DRIVER_CONNECTION, "true");
//Connection property to enable single shard transaction support. If this property is not set,
// by default all the transactions are started on catalog DB. When setting this property value
// to "true", applications must ensure that all the transactions span over a single shard only.
prop.setProperty(oracle.jdbc.OracleConnection.CONNECTION_PROPERTY_ALLOW_SINGLE_SHARD_TRANSACTION_SUPPORT, "true");
ds.setConnectionProperties(prop);
return ds;
}
}