<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Spring Archives - Truiton</title>
	<atom:link href="https://www.truiton.com/category/spring/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.truiton.com/category/spring/</link>
	<description>Technology Reaching Us In Time - Online</description>
	<lastBuildDate>Tue, 20 Feb 2024 13:49:07 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://i0.wp.com/www.truiton.com/wp-content/uploads/2022/11/cropped-truiton_new_logo_half_white.png?fit=32%2C32&#038;ssl=1</url>
	<title>Spring Archives - Truiton</title>
	<link>https://www.truiton.com/category/spring/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">54534495</site>	<item>
		<title>Spring Boot Hibernate &#8211; JPA GenerationType Table vs Sequence strategy with MySQL</title>
		<link>https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/</link>
					<comments>https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/#respond</comments>
		
		<dc:creator><![CDATA[Mohit Gupt]]></dc:creator>
		<pubDate>Tue, 20 Feb 2024 13:49:03 +0000</pubDate>
				<category><![CDATA[Spring]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[JPA]]></category>
		<guid isPermaLink="false">https://www.truiton.com/?p=17152</guid>

					<description><![CDATA[<p>Explaining how GenerationType TABLE and SEQUENCE works with MySQL DB in Spring boot hibernate. We will build a custom TableGenerator with prefix and compare its performance with a SequenceStyleGenerator</p>
<p>The post <a href="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/">Spring Boot Hibernate &#8211; JPA GenerationType Table vs Sequence strategy with MySQL</a> appeared first on <a href="https://www.truiton.com">Truiton</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large is-style-default"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?ssl=1"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="1024" height="571" data-attachment-id="17201" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-featured/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?fit=1900%2C1060&amp;ssl=1" data-orig-size="1900,1060" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Featured" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?fit=300%2C167&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?fit=1024%2C571&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?resize=1024%2C571&#038;ssl=1" alt="Spring JPA GenerationType Table vs Sequence comparison" class="wp-image-17201" srcset="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?resize=1024%2C571&amp;ssl=1 1024w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?resize=300%2C167&amp;ssl=1 300w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?resize=768%2C428&amp;ssl=1 768w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?resize=1536%2C857&amp;ssl=1 1536w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?resize=640%2C357&amp;ssl=1 640w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?resize=600%2C335&amp;ssl=1 600w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Featured.webp?w=1900&amp;ssl=1 1900w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>



<p class="has-text-align-justify">When you are building backend REST APIs and if you plan to generate identifiers or primary keys for your table records, you have to pick a primary key generation strategy which could be either one of the following AUTO, IDENTITY, SEQUENCE, TABLE or UUID. When designing a system from scratch, you always would want to pick the strategy that works best for you. I was working on a set of backend REST APIs which are built using Kotlin Spring Hibernate framework with MySQL database. For persistence and ORM I decided to use <a href="https://spring.io/projects/spring-data-jpa">Spring data JPA</a> for this project, as it is suited the best. Here in this article I wish to share my learnings on use of GenerationType.TABLE vs. GenerationType.SEQUENCE, and determine which id generation strategy is  faster when we have to dynamically generate identifiers for table records.</p>



<div class="wp-block-group has-nv-light-bg-background-color has-background" style="border-radius:20px;padding-top:var(--wp--preset--spacing--40);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40);padding-left:var(--wp--preset--spacing--40)"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-af10a197 wp-block-group-is-layout-constrained">
<p><em>I understand some people have reservations on use of MySQL database for production projects, but there are multiple factors considered when choosing a database, and it suited best for my use case. If you plan to use some other database, its your choice</em>.</p>
</div></div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Problem Statement: How to generate String identifiers with a prefix with Spring boot using JPA</h2>



<p>As mentioned, I am using MySQL database with Hibernate and Spring data JPA. For few of my tables I had a requirement to have simple numerical identifiers like 1,2,3,4 and so on. But for some of the tables in the database I wished to have an id with prefix like:</p>



<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td class="has-text-align-center" data-align="center">ID (Primary key)</td><td class="has-text-align-center" data-align="center">Other Column</td></tr><tr><td class="has-text-align-center" data-align="center">TPA00001</td><td class="has-text-align-center" data-align="center">&#8230;</td></tr><tr><td class="has-text-align-center" data-align="center">TPA00002</td><td class="has-text-align-center" data-align="center">&#8230;</td></tr><tr><td class="has-text-align-center" data-align="center">TPA00003</td><td class="has-text-align-center" data-align="center">&#8230;</td></tr><tr><td class="has-text-align-center" data-align="center">TPA00004</td><td class="has-text-align-center" data-align="center">&#8230;</td></tr></tbody></table></figure>



<p class="has-text-align-justify">I read through a lot of posts available on the internet about how to generate an identifier with prefix and which GenerationType strategy is best for it. In most of the posts it was suggested that <code>GenereationType.IDENTITY</code> or <code>GenerationType.SEQUENCE</code> are fast and scalable enough to give a good performance. But since I wished to generate an ID which is supposed to have string characters as well as integers, IDENTITY type generation strategy was ruled out. As to utilize the true power of <code>GenereationType.IDENTITY</code>, I would need to have an <code>AUTO_INCREMENT</code> column in MySQL DB, which would have defeated the whole purpose of having a string prefix, and columns with VARCHAR cannot have <code>AUTO_INCREMENT</code> property.</p>



<div class="wp-block-group has-nv-light-bg-background-color has-background" style="border-style:none;border-width:0px;border-radius:20px;padding-top:var(--wp--preset--spacing--40);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40);padding-left:var(--wp--preset--spacing--40)"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-af10a197 wp-block-group-is-layout-constrained">
<p>My Configuration</p>



<ul class="wp-block-list">
<li>Spring Boot : 3.2.1</li>



<li>mysql-connecter-j : 8.1.0</li>



<li>HikariCP : 5.0.1</li>
</ul>
</div></div>



<p></p>



<h3 class="wp-block-heading" id="Custom-SequenceGenerator">Implementing Custom SequenceGenerator with Spring boot JPA using MySQL DB</h3>



<p class="has-text-align-justify">In some of the posts on the internet it is suggested that identifier generation strategy <code>GenerationType.SEQUENCE</code> is one of the best strategies available. But given our use case we are using MySQL DB in this implementation, and as we know MySQL DB does not support sequences. Therefore if we wish to use SequenceGenerator strategy in Spring boot JPA using MySQL DB, then we need go with some workarounds. Since MySQL does not support the sequences, but still if we want to use this strategy, we have to create a sequence table which would maintain the <code>next_val</code> counter for the records in our table. JPA in Hibernate is built in such a way that SequenceGenerator strategy can work with a table as well in the case of MySQL. So to implement the same one can create a <code>TABLE_NAME_seq</code> table and use it with Spring data JPA in Hibernate. I created following table via SQL:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="EnlighterJSRAW" data-enlighter-language="sql" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">CREATE TABLE IF NOT EXISTS `cosmos`.`my_table_seq` (
  `name` VARCHAR(45) NOT NULL,
  `next_val` BIGINT(20) NULL DEFAULT NULL,
  PRIMARY KEY (`name`))</pre>
</div></div>



<div class="wp-block-group has-nv-light-bg-background-color has-background" style="border-radius:20px;padding-top:var(--wp--preset--spacing--40);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40);padding-left:var(--wp--preset--spacing--40)"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-af10a197 wp-block-group-is-layout-constrained">
<p class="has-text-align-justify"><em>Also if you are using <code>spring.jpa.hibernate.ddl-auto=update</code> then it might automatically create a sequence table for each of the tables where you implement the SequenceGenerator (not tried).</em> </p>
</div></div>



<p>Next we need to add a record to this table, to get things started:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence.png?ssl=1"><img data-recalc-dims="1" decoding="async" width="243" height="103" data-attachment-id="17161" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-sequence/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence.png?fit=243%2C103&amp;ssl=1" data-orig-size="243,103" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Sequence" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence.png?fit=243%2C103&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence.png?fit=243%2C103&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence.png?resize=243%2C103&#038;ssl=1" alt="" class="wp-image-17161"/></a></figure>
</div>


<p>Now we need to build a custom Sequence Generator using the <code>SequenceStyleGenerator</code> class:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">package com.truiton.cosmos.sequences

import org.hibernate.HibernateException
import org.hibernate.MappingException
import org.hibernate.engine.spi.SharedSessionContractImplementor
import org.hibernate.id.enhanced.SequenceStyleGenerator
import org.hibernate.internal.util.config.ConfigurationHelper
import org.hibernate.service.ServiceRegistry
import org.hibernate.type.Type
import org.hibernate.type.spi.TypeConfiguration
import java.io.Serializable
import java.util.*


class StringPrefixedSequenceIdGenerator : SequenceStyleGenerator() {
    val VALUE_PREFIX_PARAMETER: String = "valuePrefix"
    val VALUE_PREFIX_DEFAULT: String = ""
    private var valuePrefix: String? = null

    val NUMBER_FORMAT_PARAMETER: String = "numberFormat"
    val NUMBER_FORMAT_DEFAULT: String = "%d"
    private var numberFormat: String? = null

    @Throws(HibernateException::class)
    override fun generate(
        session: SharedSessionContractImplementor?,
        `object`: Any?
    ): Serializable {
        return valuePrefix + String.format(numberFormat!!, super.generate(session, `object`))
    }

    @Throws(MappingException::class)
    override fun configure(type: Type?, params: Properties?, serviceRegistry: ServiceRegistry?) {
        super.configure(
            TypeConfiguration().basicTypeRegistry.getRegisteredType(Long::class.java),
            params,
            serviceRegistry
        )
        valuePrefix = ConfigurationHelper.getString(
            VALUE_PREFIX_PARAMETER,
            params, VALUE_PREFIX_DEFAULT
        )
        numberFormat = ConfigurationHelper.getString(
            NUMBER_FORMAT_PARAMETER,
            params, NUMBER_FORMAT_DEFAULT
        )
    }
}</pre>
</div></div>



<p>To use this <code>StringPrefixedSequenceIdGenerator</code>, we need reference it in our entity class by using the following:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "cosmos_sequence1")
@GenericGenerator(
    name = "cosmos_sequence1",
    type = StringPrefixedSequenceIdGenerator::class,
    parameters = [
        org.hibernate.annotations.Parameter(name = "sequence_name", value = "my_table_seq"),
        org.hibernate.annotations.Parameter(name = "increment_size", value = "50"),
        org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled-lo"),
        org.hibernate.annotations.Parameter(name = "valuePrefix", value = "TPA"),
        org.hibernate.annotations.Parameter(name = "numberFormat", value = "%05d")])
@Column(name = "id", nullable = false, length = 10)
open var id: String? = null</pre>
</div></div>



<p class="has-text-align-justify">Now when we run this, and insert any record in the database for this entity, it will generate the desired identifier format i.e. <code>TPA00001</code>. Also it will maintain the counter for increment in <code>my_table_seq</code> table, while having the pre allocated numbers in the memory. Like for this example it would hit the <code>my_table_seq</code> table once to increment after 50 inserts have happened.</p>



<p class="has-text-align-justify">This identifier generation strategy for Spring JPA works well with MySQL. But with this approach the only downside I feel is that, we have to create a sequence table corresponding to every table in our database where we need to maintain sequence strategy based IDs. If only, we could optimize this further, our database would be much cleaner. The answer to this problem is <code>GenerationType.TABLE</code>, which we&#8217;ll explore in next section. </p>



<p></p>



<h3 class="wp-block-heading" id="Custom-TableGenerator">Implementing Custom TableGenerator with Spring boot JPA using MySQL DB</h3>



<p class="has-text-align-justify">Here I will show how to implement a custom <code>TableGenerator</code> which adds a prefix to the generated incremental numeric value in Spring boot JPA using MySQL database. Also I will explain how efficiently this identifier generation strategy can be used for multiple tables when generating primary keys for records. </p>



<p class="has-text-align-justify">Internally this <code>GenerationType.TABLE</code> strategy is very similar to sequence generator. Here a single table can have multiple <code>next_val</code> counters for multiple entity tables. There are many threads available over the internet about its performance, but lets reserve this point for next section where we compare GenerationType Table vs Sequence. For now lets create a table where we can maintain primary keys for our entities:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="EnlighterJSRAW" data-enlighter-language="sql" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">CREATE TABLE IF NOT EXISTS `cosmos`.`cosmos_sequence` (
  `sequence_name` VARCHAR(255) NOT NULL,
  `next_val` BIGINT(20) NULL DEFAULT NULL,
  PRIMARY KEY (`sequence_name`))</pre>
</div></div>



<p class="has-text-align-justify">Next lets create a class for implementing a custom TableGenerator which can generate primary keys with a prefix in Spring boot JPA with MySQL. </p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">package com.truiton.cosmos.sequences

import org.hibernate.HibernateException
import org.hibernate.MappingException
import org.hibernate.engine.spi.SharedSessionContractImplementor
import org.hibernate.id.enhanced.TableGenerator
import org.hibernate.internal.util.config.ConfigurationHelper
import org.hibernate.service.ServiceRegistry
import org.hibernate.type.Type
import org.hibernate.type.spi.TypeConfiguration
import java.io.Serializable
import java.util.*


class StringPrefixedTableGenerator : TableGenerator() {
    val VALUE_PREFIX_PARAMETER: String = "valuePrefix"
    val VALUE_PREFIX_DEFAULT: String = ""
    private var valuePrefix: String? = null

    val NUMBER_FORMAT_PARAMETER: String = "numberFormat"
    val NUMBER_FORMAT_DEFAULT: String = "%d"
    private var numberFormat: String? = null

    @Throws(HibernateException::class)
    override fun generate(
        session: SharedSessionContractImplementor?,
        `object`: Any?
    ): Serializable {
        return valuePrefix + String.format(numberFormat!!, super.generate(session, `object`))
    }

    @Throws(MappingException::class)
    override fun configure(type: Type?, params: Properties?, serviceRegistry: ServiceRegistry?) {
        super.configure(
            TypeConfiguration().basicTypeRegistry.getRegisteredType(Long::class.java),
            params,
            serviceRegistry
        )
        valuePrefix = ConfigurationHelper.getString(
            VALUE_PREFIX_PARAMETER,
            params, VALUE_PREFIX_DEFAULT
        )
        numberFormat = ConfigurationHelper.getString(
            NUMBER_FORMAT_PARAMETER,
            params, NUMBER_FORMAT_DEFAULT
        )
    }
}</pre>
</div></div>



<p>Now to actually use this StringPrefixedTableGenerator we need to reference it in our entity class with all the parameters</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Id
@GenericGenerator(
    name = "my_table_sequence",
    type = StringPrefixedTableGenerator::class,
    parameters = [
        org.hibernate.annotations.Parameter(name = TableGenerator.TABLE_PARAM, value = "cosmos_sequence"),
        org.hibernate.annotations.Parameter(name = TableGenerator.SEGMENT_COLUMN_PARAM, value = "sequence_name"),
        org.hibernate.annotations.Parameter(name = TableGenerator.VALUE_COLUMN_PARAM, value = "next_val"),
        org.hibernate.annotations.Parameter(name = TableGenerator.SEGMENT_VALUE_PARAM, value = "my_table_sequence"),
        org.hibernate.annotations.Parameter(name = "initial_value", value = "1"),
        org.hibernate.annotations.Parameter(name = "increment_size", value = "50"),
        org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled-lo"),
        org.hibernate.annotations.Parameter(name = "valuePrefix", value = "TPA"),
        org.hibernate.annotations.Parameter(name = "numberFormat", value = "%05d")]
)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "my_table_sequence")
@Column(name = "id", nullable = false, length = 10)
open var id: String? = null</pre>
</div></div>



<p class="has-text-align-justify">When an insert happens through the above code, a record is created in the underlying table which we have specified for the TableGenerator(in this case <code>cosmos_sequence</code>). Once a record is created in <code>cosmos_sequence</code> Spring JPA can perform 50 inserts without referencing this underlying table. This is done by using the pooled-lo optimizer, you can read more about it in its official documentation. The above code would give us the desired identifier format <code>TPA00001</code>.</p>



<p class="has-text-align-justify">Just to share this is how your underlying sequence table would look when you would have multiple sequences for multiple entities in the same TableGenerator table:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-2.png?ssl=1"><img data-recalc-dims="1" decoding="async" width="385" height="134" data-attachment-id="17170" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-sequence-2/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-2.png?fit=385%2C134&amp;ssl=1" data-orig-size="385,134" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Sequence-2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-2.png?fit=300%2C104&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-2.png?fit=385%2C134&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-2.png?resize=385%2C134&#038;ssl=1" alt="" class="wp-image-17170" srcset="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-2.png?w=385&amp;ssl=1 385w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-2.png?resize=300%2C104&amp;ssl=1 300w" sizes="(max-width: 385px) 100vw, 385px" /></a></figure>
</div>


<p class="has-text-align-justify">Therefore, as you can see, this approach would help us in optimizing the number of tables in our database. As we have used only one table for having primary key counters for multiple entities. Also, if you do not wish to have a single table due to fault tolerance or any other factors on specific entities, you can opt for an architecture where groups of specific entities have separate sequence tables while others are combined in to groups of 8, 16 or as per your need and performance.</p>



<p class="has-text-align-justify">In many online posts I have read people mentioning about the performance for <code>TableGenerator</code> in comparison to <code>SequenceGenerator</code>, I believe things are a little different when we are building with MySQL database. In the next section I would discuss about the performance of <code>GenerationType.TABLE</code> and <code>GenerationType.SEQUENCE</code> in Hibernate using MySQL database. </p>



<h2 class="wp-block-heading" id="Comparison-TableGenerator-SequenceGenerator">Comparing Custom TableGenerator vs. SequenceGenerator performance in Spring boot JPA using MySQL DB</h2>



<p class="has-text-align-justify">When we compare <code>GenerationType.TABLE</code> vs. <code>GenerationType.SEQUENCE</code> using MySQL DB, there is not much of a difference in the implementation. Firstly, be it SEQUENCE generation strategy or the TABLE generation, both strategies when used with pooled-lo optimization, the primary key is generated in the memory itself after the insert of first record. To be clear, in both the implementations <code>next_val</code> column&#8217;s values from the underlying table(s) are fetched only once, either on first insert or after the in-memory values are completely exhausted.</p>



<p class="has-text-align-justify">Secondly, both the approaches being discussed here use row level read locking techniques to safeguard the transaction and neither of them apply a table level lock when using MySQL DB with InnoDB. To query the <code>next_val</code> from sequence tables, Spring data JPA uses the primary key in the where clause of the query in case of GenerationType.TABLE, therefore a lock is applied only on that row. While in generation type SEQUENCE strategy only a single record is supposed to be present in the sequence table, therefore only that is locked and it should not make a difference. To actually validate this hypothesis, while the first insert was happening, I logged the queries for both of these primary key generation strategies :</p>



<p>Query for generation type SEQUENCE strategy using MySQL database:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="EnlighterJSRAW" data-enlighter-language="sql" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">select next_val as id_val from my_table_seq for update
update my_table_seq set next_val= ? where next_val=?
insert into exp_pav_loc (created_on,exp_pav_id,is_deleted,loc_type,name,number,updated_on,id) values (?,?,?,?,?,?,?,?)</pre>
</div></div>



<p>Query for GenerationType.TABLE strategy using MySQL database:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="EnlighterJSRAW" data-enlighter-language="sql" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">select tbl.next_val from cosmos_sequence tbl where tbl.sequence_name=? for update
update cosmos_sequence set next_val=?  where next_val=? and sequence_name=?
insert into exp_pav_loc (created_on,exp_pav_id,is_deleted,loc_type,name,number,updated_on,id) values (?,?,?,?,?,?,?,?,?,?)</pre>
</div></div>



<p class="has-text-align-justify">As you can see in the above SQL statements both of the primary key generation strategies use <a href="https://dev.mysql.com/doc/refman/8.3/en/innodb-locking-reads.html" target="_blank" rel="noreferrer noopener">SELECT FOR UPDATE</a> statements which locks rows only under normal circumstances. This is the reason, I feel that there is not much of a difference between <code>TableGenerator</code> and <code>SequenceGenerator</code> strategy when using MySQL DB with Spring data JPA. As both of them rely on the same working strategy for maintaining the counters for <code>next_val</code>. </p>



<h3 class="wp-block-heading" id="performance-tablegenerator-sequencegenerator">Performance of TableGenerator and SequenceGenerator in Spring boot hibernate using MySQL</h3>



<p class="has-text-align-justify">To further share data on the claim that there is not much of a difference in performance of <code>GenerationType.TABLE</code> vs. <code>GenerationType.SEQUENCE</code> when using MySQL DB, I created APIs and used JMeter for performance testing. For the first test I created one REST POST API, which performs an insert on a table when called. Further I used JMeter with following load to test its performance</p>



<div class="wp-block-group has-nv-light-bg-background-color has-background" style="border-radius:20px;padding-top:var(--wp--preset--spacing--40);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40);padding-left:var(--wp--preset--spacing--40)"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-af10a197 wp-block-group-is-layout-constrained">
<p class="has-text-align-center"><strong>JMeter load config</strong></p>



<ul class="wp-block-list">
<li>Number of threads/users : 1000</li>



<li>Ramp up period (seconds) : 10</li>



<li>Loop count : 5</li>
</ul>



<p class="has-text-align-right"><em>This is equivalent to load:<br>Requests/Minute: 6000<br>Daily Active Users: 8.64 million</em></p>
</div></div>



<p class="has-text-align-justify">For the first three runs I had configured the API to use GenerationType.SEQUENCE as the primary key generation strategy using the code shared in above sections. I will log the time taken in milliseconds for an API to return response by using JMeter. Please have a look at the 15k sample results for this performance tests:</p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="150" data-attachment-id="17188" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-sequence-1-results/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?fit=1401%2C205&amp;ssl=1" data-orig-size="1401,205" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Sequence-1-Results" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?fit=300%2C44&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?fit=1024%2C150&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?resize=1024%2C150&#038;ssl=1" alt="Spring GenerationType SEQUENCE performance results" class="wp-image-17188" srcset="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?resize=1024%2C150&amp;ssl=1 1024w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?resize=300%2C44&amp;ssl=1 300w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?resize=768%2C112&amp;ssl=1 768w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?resize=640%2C94&amp;ssl=1 640w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?resize=600%2C88&amp;ssl=1 600w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-1-Results.png?w=1401&amp;ssl=1 1401w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<p>For next three runs I configured the same API to use GenerationType.TABLE, have a look at the results:</p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="152" data-attachment-id="17189" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-table-1-results/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?fit=1400%2C208&amp;ssl=1" data-orig-size="1400,208" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Table-1-Results" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?fit=300%2C45&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?fit=1024%2C152&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?resize=1024%2C152&#038;ssl=1" alt="Spring GenerationType TABLE performance results" class="wp-image-17189" srcset="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?resize=1024%2C152&amp;ssl=1 1024w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?resize=300%2C45&amp;ssl=1 300w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?resize=768%2C114&amp;ssl=1 768w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?resize=640%2C95&amp;ssl=1 640w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?resize=600%2C89&amp;ssl=1 600w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-1-Results.png?w=1400&amp;ssl=1 1400w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<p class="has-text-align-justify">As you can see that results are very similar but for better representation, lets have a look at the average of key figures to compare the performance between SequenceGenerator and TableGenerator</p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="768" data-attachment-id="17193" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-comparison-sequence-table-1-call/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?fit=1800%2C1350&amp;ssl=1" data-orig-size="1800,1350" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?fit=300%2C225&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?fit=1024%2C768&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?resize=1024%2C768&#038;ssl=1" alt="SequenceGenerator vs. TableGenerator results comparison" class="wp-image-17193" srcset="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?resize=1024%2C768&amp;ssl=1 1024w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?resize=300%2C225&amp;ssl=1 300w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?resize=768%2C576&amp;ssl=1 768w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?resize=1536%2C1152&amp;ssl=1 1536w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?resize=640%2C480&amp;ssl=1 640w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?resize=600%2C450&amp;ssl=1 600w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-1-call.jpg?w=1800&amp;ssl=1 1800w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<p class="has-text-align-justify">As we can see these results show a very minor difference in milliseconds even at the 99th percentile. But to be completely sure, next I decided to execute a performance test between the GenerationType.SEQUENCE vs. GenerationType.TABLE with three APIs using MySQL DB on Spring data JPA. This will help us understand the behavior of TableGenerator when multiple reads/inserts/updates happen in the same sequence table. </p>



<p class="has-text-align-justify">To do this I created three different REST POST APIs, which run an insert statement on the desired table based on the code shared in above sections. Then I configured JMeter to call these APIs sequentially in a thread group, but since I am planning to have multiple threads, eventually all of these would be called in parallel.  </p>



<div class="wp-block-group has-nv-light-bg-background-color has-background" style="border-radius:20px;padding-top:var(--wp--preset--spacing--40);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40);padding-left:var(--wp--preset--spacing--40)"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-af10a197 wp-block-group-is-layout-constrained">
<p class="has-text-align-center"><strong>JMeter load config</strong></p>



<ul class="wp-block-list">
<li>Number of threads/users : 1000</li>



<li>Ramp up period (seconds) : 10</li>



<li>Loop count : 5</li>
</ul>



<p class="has-text-align-right"><em>This is equivalent to load:<br>Requests/Minute: 18000<br>Daily Active Users: 8.64 million</em></p>
</div></div>



<p>For the first three runs I configured the APIs to use <code>GenerationType.SEQUENCE</code> as the primary key generation strategy. Through this performance test I will log their response time in milliseconds. Please have a look at the data gathered, in total I captured roughly 45K samples in 3 runs of 15K each, where internally 3 APIs were being called:</p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="150" data-attachment-id="17196" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-sequence-3-results/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?fit=1400%2C205&amp;ssl=1" data-orig-size="1400,205" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Sequence-3-Results" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?fit=300%2C44&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?fit=1024%2C150&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?resize=1024%2C150&#038;ssl=1" alt="" class="wp-image-17196" srcset="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?resize=1024%2C150&amp;ssl=1 1024w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?resize=300%2C44&amp;ssl=1 300w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?resize=768%2C112&amp;ssl=1 768w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?resize=640%2C94&amp;ssl=1 640w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?resize=600%2C88&amp;ssl=1 600w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Sequence-3-Results.png?w=1400&amp;ssl=1 1400w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<p class="has-text-align-justify">Next, I configured the same set of 3 APIs to use the <code>GenerationType.TABLE</code> strategy to generate primary keys using Spring data JPA in MySQL DB. Like all the tests performed earlier, here as well I will log response time in milliseconds. For this test I captured around 45K samples, please have a look:</p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="149" data-attachment-id="17197" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-table-3-results/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?fit=1401%2C204&amp;ssl=1" data-orig-size="1401,204" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Table-3-Results" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?fit=300%2C44&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?fit=1024%2C149&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?resize=1024%2C149&#038;ssl=1" alt="" class="wp-image-17197" srcset="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?resize=1024%2C149&amp;ssl=1 1024w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?resize=300%2C44&amp;ssl=1 300w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?resize=768%2C112&amp;ssl=1 768w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?resize=640%2C93&amp;ssl=1 640w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?resize=600%2C87&amp;ssl=1 600w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Table-3-Results.png?w=1401&amp;ssl=1 1401w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<p class="has-text-align-justify">As you can see the results are very similar when we compare both the tests for 3 APIs between the SEQUENCE generation strategy and TABLE generation strategy. For better representation, lets have a look at the comparison graph:</p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="768" data-attachment-id="17198" data-permalink="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/spring-jpa-generationtype-comparison-sequence-table-3-call/" data-orig-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?fit=1799%2C1350&amp;ssl=1" data-orig-size="1799,1350" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?fit=300%2C225&amp;ssl=1" data-large-file="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?fit=1024%2C768&amp;ssl=1" src="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?resize=1024%2C768&#038;ssl=1" alt="TableGenerator and Sequence Generator performance results" class="wp-image-17198" srcset="https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?resize=1024%2C768&amp;ssl=1 1024w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?resize=300%2C225&amp;ssl=1 300w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?resize=768%2C576&amp;ssl=1 768w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?resize=1536%2C1153&amp;ssl=1 1536w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?resize=640%2C480&amp;ssl=1 640w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?resize=600%2C450&amp;ssl=1 600w, https://i0.wp.com/www.truiton.com/wp-content/uploads/2024/02/Spring-JPA-GenerationType-Comparison-Sequence-Table-3-call.jpg?w=1799&amp;ssl=1 1799w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<p>Interestingly, even when we have this large range of samples the difference between performance of <code>SequenceGenerator</code> and <code>TableGenerator</code> is very minimal.  This test not just only highlights the difference but also certifies that internally the working of <code>SequenceGenerator</code> and <code>TableGenerator</code> is very similar when used for MySQL DB in Spring data JPA.  </p>



<h3 class="wp-block-heading">Difference between GenerationType.SEQUENCE and GenerationType.TABLE</h3>



<p class="has-text-align-justify">Looking at the data captured in performance tests above, I feel the only major functional difference between <code>GenerationType.SEQUENCE</code> and <code>GenerationType.TABLE</code> when used for MySQL DB via Spring data JPA is that the first one maintains the primary key <code>next_val</code> counter in separate tables vs. the later one stores the same for multiple entities in a single table. Data from the above performance tests also imply that there is no significant difference in performance when either of them is used on MySQL DB with Spring data JPA. </p>



<p class="has-text-align-justify">Another advantage of <code>GenerationType.TABLE</code> strategy is that it helps in keeping the database clean, as a single sequence counter table can be used to store the primary key counters for multiple entities. On the contrary, if one plans to use <code>GenerationType.SEQUENCE</code>, they would have to maintain equal number of sequence tables. Like, for example if you have 100 tables where primary keys need to be generated, then you need to have 100 sequence tables as well when using Spring data JPA with <code>GenerationType.SEQUENCE</code>, in MySQL DB. </p>



<p class="has-text-align-justify">On the other hand when using <code>TableGenerator</code>, you can chose to optimize according to your need, where you can plan to have one or more than one table for maintaining primary key counters, you can always have groups of entities using same sequence table based on some custom logic. Or if you have a small project you can have single sequence table as well under <code>TableGenerator</code> strategy for all your entities. When using <code>TableGenerator</code>, based on your requirement you can take a decision and build your system. I understand that there are many factors which are considered when a database is chosen for a system, but if you plan to choose MySQL database hope this article helps you decide your ID generation strategy. If this article helped you, please feel free to share it with your friends. </p>
<div class="saboxplugin-wrap" itemtype="http://schema.org/Person" itemscope itemprop="author"><div class="saboxplugin-tab"><div class="saboxplugin-gravatar"><img alt='Mohit Gupt' src='https://secure.gravatar.com/avatar/a816092ad56645d2635ccfceb9f7e9d44821c19dec126cb394c882ba574eaa04?s=100&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/a816092ad56645d2635ccfceb9f7e9d44821c19dec126cb394c882ba574eaa04?s=200&#038;d=mm&#038;r=g 2x' class='avatar avatar-100 photo' height='100' width='100' itemprop="image"/></div><div class="saboxplugin-authorname"><a href="https://www.truiton.com/author/mohitgupt/" class="vcard author" rel="author"><span class="fn">Mohit Gupt</span></a></div><div class="saboxplugin-desc"><div itemprop="description"><p>Born in New Delhi, India. A software engineer by profession, an android enthusiast and mobile development evangelist. My motive here is to create a group of skilled engineers, who can build better software. Reason being programming is my passion, and also it feels good to make a device do something you want. Professionally I have worked with many software engineering and product development firms. As of now too, I am employed as a senior engineer in a leading tech company. In total I may have worked on more than 20 projects professionally, but whenever I get spare time I share my thoughts here at Truiton.</p>
</div></div><div class="saboxplugin-web "><a href="http://www.truiton.com" target="_self" >www.truiton.com</a></div><div class="clearfix"></div><div class="saboxplugin-socials "><a title="Wordpress" target="_blank" href="https://www.truiton.com/author/mohitgupt/" rel="nofollow noopener" class="saboxplugin-icon-grey"><svg aria-hidden="true" class="sab-wordpress" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M61.7 169.4l101.5 278C92.2 413 43.3 340.2 43.3 256c0-30.9 6.6-60.1 18.4-86.6zm337.9 75.9c0-26.3-9.4-44.5-17.5-58.7-10.8-17.5-20.9-32.4-20.9-49.9 0-19.6 14.8-37.8 35.7-37.8.9 0 1.8.1 2.8.2-37.9-34.7-88.3-55.9-143.7-55.9-74.3 0-139.7 38.1-177.8 95.9 5 .2 9.7.3 13.7.3 22.2 0 56.7-2.7 56.7-2.7 11.5-.7 12.8 16.2 1.4 17.5 0 0-11.5 1.3-24.3 2l77.5 230.4L249.8 247l-33.1-90.8c-11.5-.7-22.3-2-22.3-2-11.5-.7-10.1-18.2 1.3-17.5 0 0 35.1 2.7 56 2.7 22.2 0 56.7-2.7 56.7-2.7 11.5-.7 12.8 16.2 1.4 17.5 0 0-11.5 1.3-24.3 2l76.9 228.7 21.2-70.9c9-29.4 16-50.5 16-68.7zm-139.9 29.3l-63.8 185.5c19.1 5.6 39.2 8.7 60.1 8.7 24.8 0 48.5-4.3 70.6-12.1-.6-.9-1.1-1.9-1.5-2.9l-65.4-179.2zm183-120.7c.9 6.8 1.4 14 1.4 21.9 0 21.6-4 45.8-16.2 76.2l-65 187.9C426.2 403 468.7 334.5 468.7 256c0-37-9.4-71.8-26-102.1zM504 256c0 136.8-111.3 248-248 248C119.2 504 8 392.7 8 256 8 119.2 119.2 8 256 8c136.7 0 248 111.2 248 248zm-11.4 0c0-130.5-106.2-236.6-236.6-236.6C125.5 19.4 19.4 125.5 19.4 256S125.6 492.6 256 492.6c130.5 0 236.6-106.1 236.6-236.6z"></path></svg></span></a><a title="Twitter" target="_blank" href="http://twitter.com/mohitgupt" rel="nofollow noopener" class="saboxplugin-icon-grey"><svg aria-hidden="true" class="sab-twitter" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M26.37,26l-8.795-12.822l0.015,0.012L25.52,4h-2.65l-6.46,7.48L11.28,4H4.33l8.211,11.971L12.54,15.97L3.88,26h2.65 l7.182-8.322L19.42,26H26.37z M10.23,6l12.34,18h-2.1L8.12,6H10.23z" /></svg></span></a><a title="Facebook" target="_blank" href="https://www.facebook.com/Mr.Mohit.Gupt" rel="nofollow noopener" class="saboxplugin-icon-grey"><svg aria-hidden="true" class="sab-facebook" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 264 512"><path fill="currentColor" d="M76.7 512V283H0v-91h76.7v-71.7C76.7 42.4 124.3 0 193.8 0c33.3 0 61.9 2.5 70.2 3.6V85h-48.2c-37.8 0-45.1 18-45.1 44.3V192H256l-11.7 91h-73.6v229"></path></svg></span></a></div></div></div><p>The post <a href="https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/">Spring Boot Hibernate &#8211; JPA GenerationType Table vs Sequence strategy with MySQL</a> appeared first on <a href="https://www.truiton.com">Truiton</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.truiton.com/2024/02/spring-boot-hibernate-jpa-generationtype-table-vs-sequence-strategy-with-mysql/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">17152</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 
Minified using Disk

Served from: www.truiton.com @ 2026-04-16 16:24:15 by W3 Total Cache
-->