Showing posts with label uuid. Show all posts
Showing posts with label uuid. Show all posts

Tuesday, 21 November 2023

A Beginner's Guide to UUID Types

UUID stands for "Universally Unique Identifier." It's a way to give a unique identity to something, like a piece of information or an object, in the world of computing. The key word here is "unique" – it means that no two things should have the same UUID.

 

For example, Think of it like an Aadhar number for a person. Each person has a unique Aadhar number that helps to identify the person.

 

Different versions of UUIDs

UUID v1 (Time-based)

UUID type 1 use the current timestamp with a node identifier to generate a unique code.

 

UUID v2 (DCE Security)

UUID v2 closely resembles UUID v1, with the addition of an enhanced security layer. It strengthens security by substituting the least significant bits of the clock sequence and timestamp with a local domain number and a meaningful identifier. This modification renders UUID v2 particularly well-suited for applications with elevated security requirements.

 

UUID v3 (MD5-based name UUID)

UUID v3 generates a unique code based on a combination of a namespace and a name. It uses the MD5 hashing algorithm to convert the namespace and name into a 128-bit hash value, which is then used to create the UUID. This type of UUID is useful for identifying objects within a specific namespace, such as files in a file system.

 

UUID v4 (Random UUID)

UUID v4 is the most commonly used type of UUID. It generates a completely random 128-bit code, ensuring that the UUID is extremely unlikely to collide with any other UUID.

 

UUID v5 (SHA-1-based name UUID)

Just like UUID v3, UUID v5 creates a special code using a mix of a category and a name. The difference is that it uses SHA-1 to make this code. This type of UUID is good for applications that need both a one-of-a-kind code and extra security.

 

Deterministic and non-deterministic UUIDs

A deterministic UUID is made from an input that you can expect, so if you use the same input, you'll always get the same result. On the other hand, a non-deterministic UUID comes from a random input, so you always get a different result.

 

People often use deterministic UUIDs when they need to consistently identify the same thing over time. For instance, they're commonly employed to create UUIDs for database records. On the flip side, non-deterministic UUIDs are preferred in situations where privacy is crucial. For example, they're frequently used to generate UUIDs for user sessions.

 

UUID type 2, 3 and 5 are deterministic algorithms, whereas type 1 and 4 are non-deterministic algorithms.

 

Following utility class generate uuid for the types 1, 3, 4 and 5.

 

UUIDGenerator.java

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

public class UUIDGenerator {

	private static long getNodeId() {
		try {
			NetworkInterface networkInterface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
			byte[] macAddress = networkInterface.getHardwareAddress();

			if (macAddress != null) {
				long nodeID = 0;

				for (int i = 0; i < 6; i++) {
					nodeID = (nodeID << 8) | (macAddress[i] & 0xFF);
				}

				return nodeID;
			}
		} catch (Exception e) {
			// Ignore exception
		}

		return (long) Math.random() * Long.MAX_VALUE;
	}

	public static UUID generateUUID1() {
		long timestamp = System.currentTimeMillis();
		long nodeID = getNodeId();

		return new UUID(timestamp, nodeID);
	}

	public static UUID generateUUID3(String namespace, String name) {
		return generateNameBasedUUID(namespace, name, "MD5", 3);
	}

	public static UUID generateUUID4() {
		return UUID.randomUUID();
	}

	public static UUID generateUUID5(String namespace, String name) {
		return generateNameBasedUUID(namespace, name, "SHA-1", 5);
	}

	private static UUID generateNameBasedUUID(String namespace, String name, String algorithm, int version) {
		try {
			MessageDigest md = MessageDigest.getInstance(algorithm);
			md.update(namespace.getBytes(StandardCharsets.UTF_8));
			md.update(name.getBytes(StandardCharsets.UTF_8));

			byte[] hashBytes = md.digest();
			hashBytes[6] &= 0x0F; // Clear version
			hashBytes[6] |= (version << 4); // Set version
			hashBytes[8] &= 0x3F; // Clear variant
			hashBytes[8] |= 0x80; // Set variant

			return new UUID(bytesToLong(hashBytes, 0), bytesToLong(hashBytes, 8));
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("Hash algorithm not available: " + algorithm, e);
		}
	}

	private static long bytesToLong(byte[] bytes, int offset) {
		long result = 0;
		for (int i = 0; i < 8; i++) {
			result = (result << 8) | (bytes[offset + i] & 0xFF);
		}
		return result;
	}

	public static void main(String[] args) {
		// Generate and validate UUIDs for all types
		UUID uuid1 = generateUUID1();
		UUID uuid3 = generateUUID3("my-namespace", "my-name");
		UUID uuid4 = generateUUID4();
		UUID uuid5 = generateUUID5("my-namespace", "my-name");

		// Print results
		System.out.println("UUID1: " + uuid1);
		System.out.println("UUID3: " + uuid3);
		System.out.println("UUID4: " + uuid4);
		System.out.println("UUID5: " + uuid5);
	}
}

Output

UUID1: 0000018b-f105-d3b7-0000-88665a4dab02
UUID3: be96d0ea-c5a5-3fcc-b188-e7af3cbac3a7
UUID4: ea800779-1b58-4844-81eb-51a95500ffbb
UUID5: 071be3ef-e459-534e-87a9-cc4f96725002



  

You may like

Interview Questions

Implement retry handler for a task in Java

Design an utility class to capture application metrics summary in Java

Utility class to get primitive type from wrapper type and vice versa

FNV hash algorithm implementation in Java

Controlling Randomness in Java: Exploring the Role of Seeds in java.util.Random

Calculating initial capacity from expected size and load factor

Saturday, 17 December 2022

Hibernate 6: How to generate UUIDs as primary keys?

In this post, I am going to explain how to generate UUIDs as primary keys.

 

Using JPA 3.1

From JPA 3.1 onwards, by setting the generated value strategy to 'GenerationType.UUID', you can request the persistence provider to generare a random UUID value.


@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

 

Using @UuidGenerator annotation

‘@UuidGenerator’ annotation is added in Hibernate 6, and specifies that an entity identifier is generated as an RFC 4122 UUID.

@Id
@GeneratedValue
@UuidGenerator
private UUID id;

 

Find the below working application.

 

Step 1: Create new maven project ‘hibernate-uuid-generation’.

 

Step 2: Update pom.xml with maven dependencies.

 

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sample.app</groupId>
    <artifactId>hibernate-uuid-generation</artifactId>
    <version>1</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <java.version>15</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>

    </properties>

    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>2.1.214</version>
        </dependency>


        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.1.2.Final</version>
        </dependency>

        <dependency>
            <groupId>jakarta.persistence</groupId>
            <artifactId>jakarta.persistence-api</artifactId>
            <version>3.1.0</version>
        </dependency>

    </dependencies>
</project>

 

Step 3: Define Employee entity.

 

Employee.java

package com.sample.app.entity;

import java.util.Locale;
import java.util.UUID;

import org.hibernate.annotations.UuidGenerator;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "employees")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    @UuidGenerator
    private UUID id;

    /*
     * @Id
     * @GeneratedValue
     * @UuidGenerator private UUID id;
     */

    private String name;

    private Locale userLocale;

    public Employee(String name, Locale userLocale) {
        this.name = name;
        this.userLocale = userLocale;
    }

    public UUID getId() {
        return id;
    }

    public void setId(UUID id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Locale getUserLocale() {
        return userLocale;
    }

    public void setUserLocale(Locale userLocale) {
        this.userLocale = userLocale;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", userLocale=" + userLocale + "]";
    }

}

Step 4: Create hibernate.cfg.xml file under src/main/resources folder.

 

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="connection.driver_class">org.h2.Driver</property>
        <property name="connection.url">jdbc:h2:mem:test</property>
        <property name="connection.username">admin</property>
        <property name="connection.password">admin</property>
        <property name="connection.pool_size">1</property>

        <property name="dialect">org.hibernate.dialect.H2Dialect</property>
        <!-- Echo the SQL to stdout -->
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="current_session_context_class">thread</property>
        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">create-drop</property>
        
        <!-- dbcp connection pool configuration -->
        <property name="hibernate.dbcp.initialSize">2</property>
        <property name="hibernate.dbcp.maxTotal">10</property>
        <property name="hibernate.dbcp.maxIdle">5</property>
        <property name="hibernate.dbcp.minIdle">3</property>
        <property name="hibernate.dbcp.maxWaitMillis">-1</property>

        <!-- mappings for annotated classes -->
        <mapping class="com.sample.app.entity.Employee" />

    </session-factory>

</hibernate-configuration>

Step 5: Define main application class.

 

App.java

package com.sample.app;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Locale;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import com.sample.app.entity.Employee;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;

public class App {
    private static SessionFactory sessionFactory = buildSessionFactory();

    private static <T> List<T> loadAllData(Class<T> clazz, Session session) {
        final CriteriaBuilder builder = session.getCriteriaBuilder();
        final CriteriaQuery<T> criteria = builder.createQuery(clazz);
        criteria.from(clazz);
        return session.createQuery(criteria).getResultList();
    }

    private static SessionFactory buildSessionFactory() {
        try {
            if (sessionFactory == null) {
                StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
                        .configure("hibernate.cfg.xml").build();

                Metadata metaData = new MetadataSources(standardRegistry).getMetadataBuilder().build();

                sessionFactory = metaData.getSessionFactoryBuilder().build();
            }
            return sessionFactory;
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static void main(String args[]) throws ClassNotFoundException, IOException, URISyntaxException {

        Employee emp = new Employee("Krishna", Locale.ENGLISH);

        try (Session session = sessionFactory.openSession()) {
            session.beginTransaction();
            session.persist(emp);
            session.flush();
            session.getTransaction().commit();

            List<Employee> emps = loadAllData(Employee.class, session);
            for (Employee emp1 : emps) {
                System.out.println(emp1);

            }

        }

    }
}

Total project structure looks like below.





 

Run App.java, you will see below messages in the console.

Aug 18, 2022 4:26:49 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 18, 2022 4:26:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 18, 2022 4:26:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.h2.Driver
Aug 18, 2022 4:26:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:h2:mem:test]
Aug 18, 2022 4:26:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=admin}
Aug 18, 2022 4:26:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 18, 2022 4:26:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 1 (min=1)
Aug 18, 2022 4:26:49 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Aug 18, 2022 4:26:50 PM org.hibernate.metamodel.internal.EntityInstantiatorPojoStandard resolveConstructor
INFO: HHH000182: No default (no-argument) constructor for class: com.sample.app.entity.Employee (class must be instantiated by Interceptor)
Hibernate: 
    
    drop table if exists employees cascade 
Aug 18, 2022 4:26:50 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@4f3faa70] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate: 
    
    create table employees (
       id uuid not null,
        name varchar(255),
        userLocale varchar(255),
        primary key (id)
    )
Aug 18, 2022 4:26:50 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@3762c4fc] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate: 
    insert 
    into
        employees
        (name, userLocale, id) 
    values
        (?, ?, ?)
Hibernate: 
    select
        e1_0.id,
        e1_0.name,
        e1_0.userLocale 
    from
        employees e1_0
Employee [id=d93b5807-5e8a-4862-8ab2-e5fe83791ce9, name=Krishna, userLocale=en]

You can download this application from this link.


Previous                                                    Next                                                    Home

Friday, 21 February 2020

Cassandra: How to insert hard coded uuid value via cqlsh?

In my previous post, I explained how to insert a uuid into a table using uuid() function. There are situations, where you have a uuid, and want to insert into a table.

How to insert hard coded uuid value?
Just insert as it is.

Example
INSERT INTO cassandratutorial.employee(id, first_name) VALUES (5987fd93-1783-4a14-a17a-5fc4fb191c2c, 'Krishna');

CQL Code snippet
CREATE KEYSPACE cassandratutorial WITH REPLICATION = 
{ 
  'class' : 'SimpleStrategy', 
  'replication_factor' : 1 
};

CREATE TABLE IF NOT EXISTS cassandratutorial.employee (
  id uuid PRIMARY KEY, 
  first_name VARCHAR
);

INSERT INTO cassandratutorial.employee(id, first_name) VALUES (5987fd93-1783-4a14-a17a-5fc4fb191c2c, 'Krishna');

Cqlsh console output
cqlsh> CREATE KEYSPACE cassandratutorial WITH REPLICATION = 
   ... { 
   ...   'class' : 'SimpleStrategy', 
   ...   'replication_factor' : 1 
   ... };
cqlsh> 
cqlsh> CREATE TABLE IF NOT EXISTS cassandratutorial.employee (
   ...   id uuid PRIMARY KEY, 
   ...   first_name VARCHAR
   ... );
cqlsh> 
cqlsh> INSERT INTO cassandratutorial.employee(id, first_name) VALUES (5987fd93-1783-4a14-a17a-5fc4fb191c2c, 'Krishna');
cqlsh> 
cqlsh> SELECT * FROM cassandratutorial.employee;

 id                                   | first_name
--------------------------------------+------------
 5987fd93-1783-4a14-a17a-5fc4fb191c2c |    Krishna

(1 rows)




Previous                                                    Next                                                    Home

Cassandra: How to generate uuid?

'uuid()' function generates an uuid of type 4.

Example
INSERT INTO cassandratutorial.employee(id, first_name) VALUES (uuid(), 'Krishna');

CQL code snippet
CREATE KEYSPACE cassandratutorial WITH REPLICATION = 
{ 
  'class' : 'SimpleStrategy', 
  'replication_factor' : 1 
};

CREATE TABLE IF NOT EXISTS cassandratutorial.employee (
  id uuid PRIMARY KEY, 
  first_name VARCHAR
);

INSERT INTO cassandratutorial.employee(id, first_name) VALUES (uuid(), 'Krishna');

Cqlsh console output
cqlsh> CREATE KEYSPACE cassandratutorial WITH REPLICATION = 
   ... { 
   ...   'class' : 'SimpleStrategy', 
   ...   'replication_factor' : 1 
   ... };
cqlsh> 
cqlsh> CREATE TABLE IF NOT EXISTS cassandratutorial.employee (
   ...   id uuid PRIMARY KEY, 
   ...   first_name VARCHAR
   ... );
cqlsh> 
cqlsh> INSERT INTO cassandratutorial.employee(id, first_name) VALUES (uuid(), 'Krishna');
cqlsh> 
cqlsh> SELECT * FROM cassandratutorial.employee;

 id                                   | first_name
--------------------------------------+------------
 5987fd93-1783-4a14-a17a-5fc4fb191c2c |    Krishna

(1 rows)




Previous                                                    Next                                                    Home

Cassandra: uuid data type

Below table summarizes the uuid support of Cassandra.

Data Type
Description
uuid
Type 1 or type 4 UUID

Example
CREATE TABLE IF NOT EXISTS cassandratutorial.employee (
  id INT PRIMARY KEY, 
  first_name VARCHAR,
  description BLOB,
  male BOOLEAN,
  salary DOUBLE,
  ip_address inet,
  date_of_birth date,
  joining_time timestamp,
  unique_id uuid
);

INSERT INTO cassandratutorial.employee (id, first_name, description, male, salary, ip_address, date_of_birth, joining_time, unique_id) VALUES (1, 'Krishna', textAsBlob('I am Krishna, I am intrested in blogging, trekking'), true, 12345.67, '192.168.2.3', '1985-05-24', 1555494268, uuid());

cqlsh> CREATE KEYSPACE cassandratutorial WITH REPLICATION = 
   ... { 
   ...   'class' : 'SimpleStrategy', 
   ...   'replication_factor' : 1 
   ... };
cqlsh> 
cqlsh> CREATE TABLE IF NOT EXISTS cassandratutorial.employee (
   ...   id INT PRIMARY KEY, 
   ...   first_name VARCHAR,
   ...   description BLOB,
   ...   male BOOLEAN,
   ...   salary DOUBLE,
   ...   ip_address inet,
   ...   date_of_birth date,
   ...   joining_time timestamp,
   ...   unique_id uuid
   ... );
cqlsh> 
cqlsh> INSERT INTO cassandratutorial.employee (id, first_name, description, male, salary, ip_address, date_of_birth, joining_time, unique_id) VALUES (1, 'Krishna', textAsBlob('I am Krishna, I am intrested in blogging, trekking'), true, 12345.67, '192.168.2.3', '1985-05-24', 1555494268, uuid());
cqlsh> 
cqlsh> SELECT * FROM cassandratutorial.employee;

 id | date_of_birth | description                                                                                            | first_name | ip_address  | joining_time                    | male | salary   | unique_id
----+---------------+--------------------------------------------------------------------------------------------------------+------------+-------------+---------------------------------+------+----------+--------------------------------------
  1 |    1985-05-24 | 0x4920616d204b726973686e612c204920616d20696e7472657374656420696e20626c6f6767696e672c207472656b6b696e67 |    Krishna | 192.168.2.3 | 1970-01-19 00:04:54.268000+0000 | True | 12345.67 | bba0d1c0-b4c1-4e14-b36e-8ac2d2519bd3

(1 rows)
cqlsh>




Previous                                                    Next                                                    Home