{"id":675359,"date":"2026-01-28T10:59:06","date_gmt":"2026-01-28T09:59:06","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=675359"},"modified":"2026-02-02T14:04:36","modified_gmt":"2026-02-02T13:04:36","slug":"spring-data-jdbc-made-easy-with-intellij-idea","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/idea\/2026\/01\/spring-data-jdbc-made-easy-with-intellij-idea\/","title":{"rendered":"Spring Data JDBC Made Easy with IntelliJ IDEA"},"content":{"rendered":"\n<p>IntelliJ IDEA is well-known for its Spring Framework support. The IDE helps with bean navigation, on-the-go bean injection, Spring Data methods completion, and assistance with generating HTTP requests for controllers. One of the areas that IDEA is good at is dealing with JPA. You, as a developer, can:<\/p>\n\n\n\n<ul>\n<li>Generate entities based on DB tables.<\/li>\n\n\n\n<li>Create diff scripts for Liquibase and Flyway on model changes.<\/li>\n\n\n\n<li>Compare two DB versions and generate a diff script.<\/li>\n<\/ul>\n\n\n\n<p><br>Before IntelliJ IDEA 2025.3, dealing with Spring Data JDBC required more effort. After creating a table or adding a field, you had to update the code manually or invoke an AI. Finally, we introduce first-class support for Spring Data JDBC. This means the IDE now understands your JDBC entities just as well as it understands JPA and provides the same functionality. Whether you prefer creating a DB schema first or building a proper object model, you can leverage IDEA\u2019s features for your work.<\/p>\n\n\n\n<p>In this article, we\u2019ll try to answer the most common questions that usually come up in different daily tasks. We\u2019ll use the following domain model containing <strong>Courses<\/strong>, <strong>Students<\/strong> and <strong>Enrollments<\/strong> as an example.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"868\" height=\"179\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/spring-data-jdbc-demo-schema.png\" alt=\"\" class=\"wp-image-675360\"\/><\/figure>\n\n\n\n<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 courses\n(\n   id          int primary key auto_increment,\n   name        varchar(255) not null,\n   description text\n);\n\ncreate table students\n(\n   id    int primary key auto_increment,\n   name  varchar(255) not null,\n   email varchar(255) not null unique\n);\n\ncreate table enrollments\n(\n   student_id  int       not null,\n   course_id   int       not null,\n   enrolled_at timestamp not null,\n   primary key (student_id, course_id),\n   foreign key (student_id) references students (id),\n   foreign key (course_id) references courses (id)\n);<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Started<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: How do I connect IntelliJ IDEA to my database for reverse engineering and diff?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>Click on the <strong>Database<\/strong> tool window \u2192 Click on <strong>\u201c+\u201d<\/strong> icon \u2192 Data Source \u2192 MySQL<\/p>\n\n\n\n<p>Provide database connection properties and click on <strong>Test Connection<\/strong> to verify the connectivity. Click <strong>OK<\/strong> to connect to your database.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/1-connect-to-database-mysql.mp4\"><\/video><\/figure>\n\n\n\n<p>If you have datasource properties configured in your <strong><em>application.properties\/yml<\/em><\/strong> file then you can register DataSource by simply clicking on the gutter icon.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/14-register-ds-from-props.mp4\"><\/video><\/figure>\n\n\n\n<p>On the other hand, if you have DataSource registered in the Database tool window, then you can simply drag the connection onto the <strong><em>application.properties\/yml<\/em><\/strong> file to configure the datasource properties.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/15-app-props-from-ds.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: How does IntelliJ IDEA detect Spring Data JDBC entities and repositories?<\/strong><\/h3>\n\n\n\n<p><strong>A:<\/strong> IntelliJ IDEA detects classes with <strong>@Id (org.springframework.data.annotation.Id) <\/strong>annotated properties as Spring Data JDBC entities.&nbsp;<\/p>\n\n\n\n<p>Any interface that extends either <code>org.springframework.data.repository.Repository<\/code> or any of its sub-interfaces(<code>CrudRepository<\/code>, <code>ListCrudRepository<\/code>, <code>PagingAndSortingRepository<\/code>, etc.) will be automatically detected as Spring Data Repositories.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: IDEA does not detect my entity, what should I do?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>In case the automatic detection of entities is not working (for example, currently records with <code>@Id<\/code> properties without <code>@Table<\/code> annotation are not automatically detected), then you can explicitly mark them as Spring Data JDBC entities by adding <code>@Table<\/code> annotation on the class\/record or by adding them to Mapping Context as follows:<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/3-mark-bean-as-entity.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: DB-first or code-first: which workflow should I choose for Spring Data JDBC?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>From <a href=\"https:\/\/docs.spring.io\/spring-data\/relational\/reference\/jdbc\/domain-driven-design.html\" target=\"_blank\" rel=\"noopener\">Spring Data Documentation<\/a>:<\/p>\n\n\n\n<p><em>All Spring Data modules are inspired by the concepts of \u201crepository\u201d, \u201caggregate\u201d, and \u201caggregate root\u201d from Domain Driven Design. These are possibly even more important for Spring Data JDBC, because they are, to some extent, contrary to normal practice when working with relational databases.<\/em><\/p>\n\n\n\n<p>While using Spring Data JDBC, it is recommended to follow DDD and start with domain models\/entities first.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: When should I use IntelliJ IDEA\u2019s built-in Spring Data JDBC features instead of asking an AI to generate code?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>You can use AI <strong>planning mode to brainstorm the design<\/strong> and use <strong>IntelliJ IDEA\u2019s built-in code generation feature to deterministically generate code<\/strong>.&nbsp;<\/p>\n\n\n\n<p>If you are following the <strong>code-first<\/strong> approach, you can generate the models using AI and use IntelliJ IDEA to generate Flyway\/Liquibase migrations from the entities.&nbsp;<br><br>Conversely, if you are following the <strong>database-first<\/strong> approach, then you can generate Entities from the existing schema deterministically without any AI and its associated cost.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: What are the current limitations vs JPA support (and where does the IDE intentionally stay hands-off)?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>IntelliJ IDEA provides all the necessary support for working with Spring Data JPA and Spring Data JDBC. So, it boils down to the comparison of Spring Data JDBC vs Spring Data JPA features.<br><br>IntelliJ IDEA provides support for both <strong>Spring Data JPA<\/strong> and <strong>Spring Data JDBC<\/strong> with the following:<\/p>\n\n\n\n<ul>\n<li>Generating entities from an existing database schema<\/li>\n\n\n\n<li>Initializing Flyway\/Liquibase migrations from entities<\/li>\n\n\n\n<li>Generating database migrations from code changes<\/li>\n\n\n\n<li>Synchronizing database changes into entities<\/li>\n\n\n\n<li>Autocompletion of Spring Data Repository methods<\/li>\n\n\n\n<li>On-demand creation of Spring Data Repository methods<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Schema Evolution and Migration<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: How do I generate @Table entities from an existing database schema?<\/strong><\/h3>\n\n\n\n<p><strong>A:<\/strong> In the <strong>Database<\/strong> tool window, right-click on the DataSource connection and select <strong>\u201cCreate JDBC Entities from DB\u2026\u201d<\/strong>, select the <strong>Target package<\/strong>, select the tables you want to generate entities for, and click <strong>OK<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/2-generate-jdbc-entities-from-db.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: How does IntelliJ IDEA handle composite keys during reverse engineering?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>While generating Spring Data JDBC entities from the existing schema, for composite keys IntelliJ IDEA generates a class for the ComposeKey and uses <code>@Embedded<\/code> annotation to define the primary key.<\/p>\n\n\n\n<p>In our example, the <code>enrollments<\/code> table composite key <code>EnrollmentId<\/code> is generated as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class EnrollmentId {\n   private Integer studentId = 0;\n   private Integer courseId = 0;\n\n   \/\/ setters and getters\n}\n\n@Table(name = \"enrollments\")\npublic class Enrollment {\n   @Id\n   @Embedded.Nullable\n   private EnrollmentId id;\n\n   private Instant enrolledAt = Instant.now();\n\n   public Enrollment(@Nullable EnrollmentId id, Instant enrolledAt) {\n       this.id = id;\n       this.enrolledAt = enrolledAt;\n   }\n\n   \/\/ setters and getters\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: I started with the code-first approach. Can IntelliJ IDEA generate migrations from entities?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>Yes. You can generate Flyway or Liquibase Migrations from the entities. Using the entity gutter icon, invoke Flyway\/Liquibase Init Migration action, choose the entities and DataSource and generate the migrations.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/4-init-flyway-migrations.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: Can IntelliJ IDEA generate migrations from my code changes?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>IntelliJ IDEA can generate Flyway and Liquibase migrations from the code changes (adding new entities, changing or adding entity properties).<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/5-migrations-from-code-changes.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: What changes should I review manually before applying generated migrations?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>In short, ALL. While IntelliJ IDEA detects the database dialect and generates the appropriate database migration scripts, it is better to review before applying.<br><br>You should also pay attention to the migration change color codes (<mark style=\"background-color:rgba(0, 0, 0, 0);color:#12cf89\" class=\"has-inline-color\">green<\/mark>, <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">yellow<\/mark>, <mark style=\"background-color:rgba(0, 0, 0, 0);color:#f45959\" class=\"has-inline-color\">red<\/mark>) that represent <strong>safe<\/strong>, <strong>needs attention<\/strong> and <strong>dangerous<\/strong> types. The safe operations mostly create new resources(tables, columns, etc) that can be easily reverted. The <strong>needs attention <\/strong>type<strong> <\/strong>changes alter the schema (rename tables or columns, change datatypes, etc) that could have a significant impact on the application. The <strong>dangerous<\/strong> type changes are irreversible, such as dropping a column or table, which should be carefully evaluated and performed with the utmost care.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1179\" height=\"704\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/flyway-changes-color-codes.png\" alt=\"\" class=\"wp-image-676031\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: How does the &#8220;Diff &amp; migration scripts&#8221; feature handle complex changes, such as renaming a column or changing a data type, between my @Table model and the DB?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>When generating migration scripts, IntelliJ IDEA shows the different types of operation in different color codes(<mark style=\"background-color:rgba(0, 0, 0, 0);color:#11c37c\" class=\"has-inline-color\">green<\/mark>, <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">yellow<\/mark>, <mark style=\"background-color:rgba(0, 0, 0, 0);color:#eb6262\" class=\"has-inline-color\">red<\/mark>) to represent <strong>safe<\/strong>, <strong>needs attention<\/strong> and <strong>dangerous<\/strong> types.<\/p>\n\n\n\n<p>For migrations like renaming a column name or modifying data types, IntelliJ IDEA offers suggestion to rename the column name or update datatype instead of creating a new column and dropping the old column.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/12-rename-column-migration.mp4\"><\/video><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Working with Spring Data<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: In DDD, we focus on &#8220;Aggregate Roots.&#8221; How does IDEA help me stay within those boundaries?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>According to DDD principles, an entity should be associated with only one aggregate root. In IntelliJ IDEA, if you try to associate the same entity with multiple aggregates, it will show an inspection warning and provide quick fixes.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/6-ddd-inspection.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: How do I create a Spring Data JDBC repository?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>You can create Spring Data JDBC Repository by using right-click \u2192 <em>Spring Component (Java)<\/em> \u2192 <em>RepositoryName<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/7-generate-repository.mp4\"><\/video><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Productivity Hacks<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: Can I add multiple missing columns to an entity in one go?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>You can add the missing columns to an entity by right-clicking on <em>Table<\/em> \u2192 <em>Create Entity Attributes From DB<\/em> and select all the missing columns.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/9-add-missing-cols-to-entity.mp4\"><\/video><\/figure>\n\n\n\n<p>You can also add one column at a time using column auto completion support.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/13-autocomplete-single-column.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: How do I quickly create a repository and inject it into a service (end-to-end flow)?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>A simpler way is to just start typing the <code>{entityName}Repo<\/code> and IntelliJ IDEA will show an option to create Repository. It will create the Repository and automatically inject in the current bean. Similarly, you can inject any existing bean and start using it by just start typing the Spring bean name.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/8-gen-repo-inject-in-service.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Q: How &#8220;smart&#8221; is the derived method completion?<\/strong><\/h3>\n\n\n\n<p><strong>A: <\/strong>IntelliJ IDEA provides autocompletion for finder methods based on the field names of entity classes and Spring Data JDBC supported keywords.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/10-repo-method-autocompletion.mp4\"><\/video><\/figure>\n\n\n\n<p>You don\u2019t even need to create the Repository methods ahead of time. Wherever you are using the repository, you can start typing the finder method using the autocomplete feature, and IntelliJ IDEA will create that method automatically in the repository.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/01\/11-repo-method-creation-on-demand.mp4\"><\/video><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>First-class Spring Data JDBC support in IntelliJ IDEA reduces manual work in everyday JDBC tasks. If you prefer a code-first approach, the IDE helps you keep your aggregates and domain model consistent and can generate migration scripts for Flyway or Liquibase that you can review and apply. If you work DB-first, reverse engineering helps you bring database changes back into code with fewer steps. <\/p>\n\n\n\n<p>AI can definitely help you draft migrations or mappings, but it should not be the source of truth. IntelliJ IDEA inspections and database tools help you verify changes early, before they ship.<\/p>\n\n\n\n<p>Give it a try in your project, and let us know what works well and what you want to see next.<\/p>\n","protected":false},"author":1511,"featured_media":677284,"comment_status":"closed","ping_status":"closed","template":"","categories":[4759,5088],"tags":[3007,3211,3145,9011,8620],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/idea\/675359"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/users\/1511"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/comments?post=675359"}],"version-history":[{"count":8,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/idea\/675359\/revisions"}],"predecessor-version":[{"id":677443,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/idea\/675359\/revisions\/677443"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media\/677284"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media?parent=675359"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/categories?post=675359"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/tags?post=675359"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/cross-post-tag?post=675359"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}