Hibernate Sharding Example
It is a simple implementation of Hibernate Sharding in java. In this we are using two databases i.e. shard1 and shard2.
All data related to "India" goes to shard1 where as others go to shard2.
Download and attach the required jar files.
All data related to "India" goes to shard1 where as others go to shard2.
Project Contents:
File Name
|
Use
|
DatabaseCreator.java
|
Used to
create tables in databases named shard1 and shard2.
|
User.java
|
POJO
class.
|
User.hbm.xml
|
Mapping
file. Used to map POJO to database tables.
|
hibernate0.cfg.xml
|
Hibernate
configuration file for database named shard1
|
hibernate1.cfg.xml
|
Hibernate
configuration file for database named shard2
|
IdGenerator.java
|
Class
for Id generation
|
HibernateShardUtil.java
|
Class
for loading hiberante session factory.
|
UserShardResolutionStrategy.java
|
Class
for implementing shard resolution strategy.
|
UserShardSelectionStrategy.java
|
Class
for implementing shard selection strategy.
|
Main.java
|
Client
class to execute the whole process.
|
DatabaseCreator.java
package test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class DatabaseCreator
{
public static void main(String args[]) throws Exception
{
String url = "jdbc:mysql://localhost/shard1";
String dbusr = "root";
String dbpwd = "root";
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, dbusr, dbpwd);
Statement statement = connection.createStatement();
String query;
query = "drop table s_usr";
statement.executeUpdate(query);
query = "create table s_usr(usr_kid integer primary key, usr_name varchar(50)," +
"usr_gender varchar(10),usr_country varchar(20))";
statement.executeUpdate(query);
statement.close();
connection.close();
url = "jdbc:mysql://localhost/shard2";
connection = DriverManager.getConnection(url, dbusr, dbpwd);
statement = connection.createStatement();
query = "drop table s_usr";
statement.executeUpdate(query);
query = "create table s_usr(usr_kid integer primary key, usr_name varchar(50)," +
"usr_gender varchar(10),usr_country varchar(20))";
statement.executeUpdate(query);
statement.close();
connection.close();
}
}
User.java
package test;
import java.io.Serializable;
public class User implements Serializable
{
protected int usr_kid;
protected String name;
protected String gender;
protected String country;
public int getUsr_kid() {
return usr_kid;
}
public void setUsr_kid(int usr_kid) {
this.usr_kid = usr_kid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString() {
return "User Id: "+ usr_kid + " , Username: " + name + " , Gender: " + gender + " , Country: " + country;
}
}
import java.io.Serializable;
public class User implements Serializable
{
protected int usr_kid;
protected String name;
protected String gender;
protected String country;
public int getUsr_kid() {
return usr_kid;
}
public void setUsr_kid(int usr_kid) {
this.usr_kid = usr_kid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString() {
return "User Id: "+ usr_kid + " , Username: " + name + " , Gender: " + gender + " , Country: " + country;
}
}
User.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test">
<class name="User" table="s_usr">
<id name="usr_kid" column="usr_kid" type="integer">
<generator class="test.IdGenerator"/>
</id>
<property name="name" column="usr_name"/>
<property name="gender" column="usr_gender"/>
<property name="country" column="usr_country"/>
</class>
</hibernate-mapping>
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test">
<class name="User" table="s_usr">
<id name="usr_kid" column="usr_kid" type="integer">
<generator class="test.IdGenerator"/>
</id>
<property name="name" column="usr_name"/>
<property name="gender" column="usr_gender"/>
<property name="country" column="usr_country"/>
</class>
</hibernate-mapping>
hibernate0.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/shard1</property>
<property name="hibernate.connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.pool_size">1</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.shard_id">0</property>
<property name="hibernate.shard.enable_cross_shard_relationship_checks">true</property>
</session-factory>
</hibernate-configuration>
hibernate1.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/shard2</property>
<property name="hibernate.connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.pool_size">1</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.shard_id">1</property>
<property name="hibernate.shard.enable_cross_shard_relationship_checks">true</property>
</session-factory>
</hibernate-configuration>
IdGenerator.java
package test;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;
public class IdGenerator implements IdentifierGenerator
{
static Integer id;
static
{
id = 0;
String url = "jdbc:mysql://localhost/shard1";
String dbusr = "root";
String dbpwd = "root";
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, dbusr, dbpwd);
Statement stmt = con.createStatement();
String query = "select max(usr_kid) from s_usr";
ResultSet rset = stmt.executeQuery(query);
if(rset.next()) {
int tempid = rset.getInt(1);
if(id<tempid)
id = tempid;
}
stmt.close();
con.close();
url = "jdbc:mysql://localhost/shard2";
con = DriverManager.getConnection(url, dbusr, dbpwd);
stmt = con.createStatement();
query = "select max(usr_kid) from s_usr";
rset = stmt.executeQuery(query);
if(rset.next()) {
int tempid = rset.getInt(1);
if(id<tempid)
id = tempid;
}
System.out.println(id);
stmt.close();
con.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Serializable generate(SessionImplementor arg0, Object arg1) throws HibernateException {
id = id +1;
return id;
}
}
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;
public class IdGenerator implements IdentifierGenerator
{
static Integer id;
static
{
id = 0;
String url = "jdbc:mysql://localhost/shard1";
String dbusr = "root";
String dbpwd = "root";
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, dbusr, dbpwd);
Statement stmt = con.createStatement();
String query = "select max(usr_kid) from s_usr";
ResultSet rset = stmt.executeQuery(query);
if(rset.next()) {
int tempid = rset.getInt(1);
if(id<tempid)
id = tempid;
}
stmt.close();
con.close();
url = "jdbc:mysql://localhost/shard2";
con = DriverManager.getConnection(url, dbusr, dbpwd);
stmt = con.createStatement();
query = "select max(usr_kid) from s_usr";
rset = stmt.executeQuery(query);
if(rset.next()) {
int tempid = rset.getInt(1);
if(id<tempid)
id = tempid;
}
System.out.println(id);
stmt.close();
con.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Serializable generate(SessionImplementor arg0, Object arg1) throws HibernateException {
id = id +1;
return id;
}
}
HibernateShardUtil.java
package test;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.shards.ShardId;
import org.hibernate.shards.ShardedConfiguration;
import org.hibernate.shards.cfg.ConfigurationToShardConfigurationAdapter;
import org.hibernate.shards.strategy.ShardStrategy;
import org.hibernate.shards.strategy.ShardStrategyFactory;
import org.hibernate.shards.strategy.ShardStrategyImpl;
import org.hibernate.shards.strategy.access.SequentialShardAccessStrategy;
import org.hibernate.shards.strategy.access.ShardAccessStrategy;
import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
public class HibernateShardUtil
{
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
static
{
try
{
Configuration config = new Configuration();
config.configure("/test/hibernate0.cfg.xml");
config.addResource("test/User.hbm.xml");
List shardConfigs = new ArrayList();
shardConfigs.add(new ConfigurationToShardConfigurationAdapter(new Configuration().configure("/test/hibernate0.cfg.xml")));
shardConfigs.add(new ConfigurationToShardConfigurationAdapter(new Configuration().configure("/test/hibernate1.cfg.xml")));
ShardStrategyFactory shardStrategyFactory = buildShardStrategyFactory();
ShardedConfiguration shardedConfig = new ShardedConfiguration(config,shardConfigs,shardStrategyFactory);
sessionFactory = shardedConfig.buildShardedSessionFactory();
}
catch (Throwable ex)
{
ex.printStackTrace();
sessionFactory = null;
}
}
static ShardStrategyFactory buildShardStrategyFactory()
{
ShardStrategyFactory shardStrategyFactory = new ShardStrategyFactory() {
public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
ShardSelectionStrategy pss = new UserShardSelectionStrategy();
ShardResolutionStrategy prs = new UserShardResolutionStrategy(shardIds);
ShardAccessStrategy pas = new SequentialShardAccessStrategy();
return new ShardStrategyImpl(pss, prs, pas);
}
};
return shardStrategyFactory;
}
}
UserShardResolutionStrategy.java
package test;
import java.util.List;
import org.hibernate.shards.ShardId;
import org.hibernate.shards.strategy.resolution.AllShardsShardResolutionStrategy;
import org.hibernate.shards.strategy.selection.ShardResolutionStrategyData;
public class UserShardResolutionStrategy extends AllShardsShardResolutionStrategy
{
public UserShardResolutionStrategy(List<ShardId> shardIds) {
super(shardIds);
}
public List<ShardId> selectShardIdsFromShardResolutionStrategyData( ShardResolutionStrategyData srsd) {
return super.selectShardIdsFromShardResolutionStrategyData(srsd);
}
}
import java.util.List;
import org.hibernate.shards.ShardId;
import org.hibernate.shards.strategy.resolution.AllShardsShardResolutionStrategy;
import org.hibernate.shards.strategy.selection.ShardResolutionStrategyData;
public class UserShardResolutionStrategy extends AllShardsShardResolutionStrategy
{
public UserShardResolutionStrategy(List<ShardId> shardIds) {
super(shardIds);
}
public List<ShardId> selectShardIdsFromShardResolutionStrategyData( ShardResolutionStrategyData srsd) {
return super.selectShardIdsFromShardResolutionStrategyData(srsd);
}
}
UserShardSelectionStrategy.java
package test;
import org.hibernate.shards.ShardId;
import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
public class UserShardSelectionStrategy implements ShardSelectionStrategy
{
public ShardId selectShardIdForNewObject(Object obj) {
if (obj instanceof User) {
int shardId = 0;
String country = ((User) obj).getCountry();
if(country.equalsIgnoreCase("India"))
shardId = 0;
else
shardId = 1;
return new ShardId(shardId);
}
throw new IllegalArgumentException();
}
}
import org.hibernate.shards.ShardId;
import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
public class UserShardSelectionStrategy implements ShardSelectionStrategy
{
public ShardId selectShardIdForNewObject(Object obj) {
if (obj instanceof User) {
int shardId = 0;
String country = ((User) obj).getCountry();
if(country.equalsIgnoreCase("India"))
shardId = 0;
else
shardId = 1;
return new ShardId(shardId);
}
throw new IllegalArgumentException();
}
}
Main.java
package test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
public class Main
{
public void list()
{
SessionFactory sessionFactory = HibernateShardUtil.getSessionFactory();
Session session = sessionFactory.openSession();
List<User> userList = session.createQuery("from User").list();
Iterator<User> iterator = userList.iterator();
while(iterator.hasNext())
{
User user = (User) iterator.next();
System.out.println(user);
}
session.close();
}
public void input()
{
SessionFactory sessionFactory = HibernateShardUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = null;
try
{
transaction = session.beginTransaction();
User user = new User();
user.setName("Max");
user.setCountry("U.S.A");
user.setGender("Male");
session.save(user);
user = new User();
user.setName("Hemant Kumar");
user.setCountry("India");
user.setGender("Male");
session.save(user);
transaction.commit();
}
catch (Exception e)
{
transaction.rollback();
e.printStackTrace();
}
session.close();
}
public static void main(String[] args)
{
Main obj = new Main();
obj.list();
obj.input();
obj.list();
}
}
Download and attach the required jar files.
A very useful article. It's very interesting that one can define their own strategies. This gives great flexibility to Hibernate Shards.
ReplyDelete