Two Almost Identical Methods Where One Works and One Returns Stack Overflow Error

In this instructor, you are going to learn more about PostgreSQL you bet to integrate it with a Spring Boot diligence. You will learn how to install a simple PostgreSQL instance using Stevedore and how to connect a Spring Boot application thereto. After that, you'll create a simple database outline and total some information thereto. Next, I'll show you how to make SQL files to deliver database changes, which are more suitable for enterprise applications. To finish, you will learn how to use PostgreSQL JSONB data structure and use PostgreSQL as a NoSQL database.

Let's dig in!

Get rolling with PostgreSQL via Dock worker

Initially proposed in the 70s, the RDBMS (Relational Database Management System) has mature in popularity through the years as computing processing power and computer memory capacity has augmented. A critical characteristic of RDBMS is the support for ACID transactions (Atomicity, Consistence, Isolation, Durability) which guarantee data body even in a concurrent environment without the developer needing to be fully aware.

PostgreSQL is combined of the most famous RDBMS roughly. Technically speaking IT is also one of the most ripe relational database systems available. Why is that? Postgres means Post Ingres operating theatre the successor of Ingres, an older database that paved the way to the more renowned Microsoft SQL Server and else products.

You will necessitate PostgreSQL installed to finish the instructor. To put in and trial run PostgreSQL, I recommend using Dock worker:

            docker pull postgres:11 longshoreman run              --diagnose              dev-postgres              -p              5432:5432              -e              POSTGRES_PASSWORD              =mysecretpassword              -d              postgres:11              # CREATE decibel coursedb              docker              EXEC              dev-postgres psql              -U              postgres              -c              "CREATE DATABASE coursedb"              postgres                      

NOTE: You will necessitate Docker installed for these commands to work.

The command above should run in whatsoever Linux, Windows, or MacOS distribution that has an instance of Docker installed. The first line pulls PostgreSQL version 11; the second line initiates a new case of information technology with the name dev-postgres, running happening port 5432. The terminal line executes a DDL command to create the database coursedb into the illustration. Sustain in mind, you are not creating a volume for the storage data if the container is deleted, all its data will beryllium deleted equally well.

Create a Reverberate Boot App with PostgreSQL

Get-go, you need to create a new project with the required dependencies. You can use Spring Initialzr for this.

New Spring Application

Configure your project as shown in the image above:

  • Externalise Type: Maven Project
  • Grouping: com.okta.developer
  • Artifact: postgresql
  • Dependencies: Web, JPA, PostgreSQL

Download the file and unzip it. Then, simply run the bid below:

NOTE: Depending on your operating system, you might need to change ./mvnw to mvnw.

Running mvnw will download Maven, all dependencies, and run the application goal (spring-boot:run over). It volition likely fail because you come non have a PostgreSQL database organized. Let's set this.

Add Database Configuration for PostgreSQL

You now possess a system of rules that has database dependencies but does not know where to connect. First, change your main class (plausibly com.okta.developer.postgresql.PostgresqlApplication) and add the annotation @EnableTransactionManagement to IT, like this:

                          package              com.okta.developer.postgresql              ;              importation              org.springframework.boot.SpringApplication              ;              import              org.springframework.boot.autoconfigure.SpringBootApplication              ;              significance              org.springframework.transaction.annotation.EnableTransactionManagement              ;              @SpringBootApplication              @EnableTransactionManagement              national              class              PostgresqlApplication              {              public              atmospheric static              null              intense              (              String              []              args              )              {              SpringApplication              .              extend to              (              PostgresqlApplication              .              class              ,              args              );              }              }                      

Configuration annotations in Spring earmark you to set up your application using type secure code. This means if something becomes inconsistent with your configuration, it will show compilation errors. The feature is a nice phylogenesis from the older XML-based constellation Spring used to have. Previously, it was possible to get runtime errors since XML and your code was non linked.

Update src/main/resources/diligence.properties to define your database connection properties:

                          spring.datasource.url              =              jdbc:postgresql://192.168.99.100:5432/coursedb              outflow.datasource.username              =              postgres              bound.datasource.password              =              mysecretpassword              spring.jpa.properties.hole up.dialect              =              org.hibernate.dialect.PostgreSQLDialect              spring.jpa.hole up.ddl-auto              =              create                      

Here's a quick explanation of each property:

  • spring.datasource.universal resource locator - describes the JDBC connection URL. Each RDBMS (like PostgreSQL, MySQL, Oracle, etc.) has its format. The IP 192.168.99.100 is the assigned aside Docker to the host auto in Windows or MacOS machines. If you are running on Linux or Mac, you must change to 127.0.0.1 every bit the Docker Innkeeper is your machine.
  • spring.datasource.username - the username you will connect to the database. You are active to use the master exploiter for this tutorial. For yield, you should create a limited user for each application.
  • spring.datasource.password - The password you position when creating PostgreSQL docker illustrate.
  • spring.jpa.properties.hibernate.dialect - Although SQL is a standard, all database has some specific syntax that is addressed by hibernate dialect.
  • spring.jpa.hole up.ddl-auto - Define if Hibernate tooshie produce, blue-pencil and create, update or validate the current Database Schema. Presently, you should set this property to create so Hibernate can handle all Database Schema.

What happens if you embark on the application again?

Now the application starts and you should Be able to assimilative http://localhost:8080 in your browser. Nix nice happens equally you haven't cursive any encode for the UI yet. You may see an mistake stack on initialization: don't worry, it is simply Hibernate telling the JDBC driver does not support a feature (method createClob).

Create JPA Entities and Data Access Objects

Oklahoma, now let's do some real work.

First of all, let's look at this tutorial's schema. Information technology has two entities:

  • Teacher
    • Columns: name, picture, email
  • Course of instruction
    • Columns: name, workload, charge per unit
    • Relationship: teacher

Before changing the cipher, add cardinal new dependencies in your pom.xml file in:

                          <dependency>              <groupId>org.projectlombok</groupId>              <artifactId>lombok</artifactId>              </dependance>              <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-data-rest</artifactId>              </dependency>                      

Project Lombok adds a serial of helpful features that simplify a developer's life the likes of getter/setter and builder autogeneration. If you are using an IDE to develop this tutorial, you must install a plugin to avoid compilation problems.

Recoil Data REST is a accessible dependency that creates an HTTP interface for your repositories. You are going to use the HTTP interface to test your code.

To help your entities, you'll create a superclass that handles the primary winder in the same way for every entity we create. PostgreSQL has support to UUID, so you are going to use it instead of the commonly in use auto-increment integer. UUID is reformatory to avoid a typical attack in which the hacker tries to increment operating theatre decrease an entity ID to find hot information.

Make the class EntityWithUUID in package com.okta.developer.postgresql.entities:

                          package              com.okta.developer.postgresql.entities              ;              import              org.hibernate.annotations.Character              ;              implication              javax.perseverance.Id              ;              import              javax.persistence.MappedSuperclass              ;              import              java.util.UUID              ;              @MappedSuperclass              public              social class              EntityWithUUID              {              @Id              @Type              (              type              =              "pg-uuid"              )              private              UUID              id              ;              public              EntityWithUUID              ()              {              this              .              ID              =              UUID              .              randomUUID              ();              }              }                      

Thither are some excellent annotations Here:

  • @MappedSuperclass says to JPA this class is a superclass of an entity and should have its attributes mapped into the entity.
  • @Id says the impute is a primary key
  • @Type specifies what type is used on the database. You motive to specify since PostgreSQL has its own type for UUIDs: pg-uuid.

Now, create the two entities in the com.okta.developer.postgresql.entities package:

Teacher.Java

                          package              com.okta.developer.postgresql.entities              ;              moment              lombok.AllArgsConstructor              ;              import              lombok.Information              ;              importation              lombok.NoArgsConstructor              ;              import              javax.persistence.Entity              ;              @Entity              @Data              @AllArgsConstructor              @NoArgsConstructor              public              separate              Teacher              extends              EntityWithUUID              {              private              String              name              ;              private              String              pictureURL              ;              close              Cosmic string              e-mail              ;              }                      

Course.Java

                          package              com.okta.developer.postgresql.entities              ;              importee              lombok.AllArgsConstructor              ;              import              lombok.Data              ;              moment              lombok.NoArgsConstructor              ;              import              javax.persistence.*              ;              @Entity              @Data              @AllArgsConstructor              @NoArgsConstructor              unrestricted              classify              Course of action              extends              EntityWithUUID              {              private              Strand              name              ;              private              int              workload              ;              private              short              rate              ;              @ManyToOne              @JoinColumn              (              foreignKey              =              @ForeignKey              (              identify              =              "fk_course_teacher"              ))              private              Instructor              teacher              ;              }                      

The annotations get a significant influence in these classes:

  • @Data - It's a Lombok annotation and tells Lombok to create getter and setter for all attributes.
  • @AllArgsConstructor - Tells Lombok to create a constructor with all year attributes
  • @NoArgsConstructor - Tells Lombok to create some other constructor with no arguments. It is useful for JPA.
  • @Entity - Indicates this class represents a persistent entity. Information technology is interpreted as a table by JPA, and the table should take the same class name unless you vary it.
  • @ManyToOne and @JoinColumn - Indicates in that respect is a Many to One family relationship whose relationship uses of a Join Column. It is possible to set the extrinsic key if Hibernate is going to create the DDL.

So far-off, so good. Like a sho, make a DAO (Data Access Object, also called a Repository by Spring) class for each entity in the com.okta.developer.postgresql.dao package:

CourseDAO.java

                          bundle              com.okta.developer.postgresql.dao              ;              import              com.okta.developer.postgresql.entities.Course              ;              implication              org.springframework.information.secretary.CrudRepository              ;              import              java.util.UUID              ;              public              user interface              CourseDAO              extends              CrudRepository              <              Run              ,              UUID              >              {}                      

TeacherDAO.java

                          packet              com.okta.developer.postgresql.dao              ;              spell              com.okta.developer.postgresql.entities.Teacher              ;              import              org.springframework.data.repository.CrudRepository              ;              import              java.util.UUID              ;              public              interface              TeacherDAO              extends              CrudRepository              <              Teacher              ,              UUID              >              {}                      

You instantly have DAOs for each entity. You may be asking, where is the implementation for them? Spring Data has some intelligent ways to handle this. Since your interfaces extend CrudRepository, Take a hop automatically generates the practical class with all CRUD-related operations ready!

To fill some data, create a radical service class named DataFillerService. It testament follow responsible for inserting data in the database as soon as the diligence starts.

DataFillerService.java

                          package              com.okta.developer.postgresql.service              ;              import              com.okta.developer.postgresql.dao.CourseDAO              ;              import              com.okta.developer.postgresql.dao.TeacherDAO              ;              import              com.okta.developer.postgresql.entities.Course              ;              import              com.okta.developer.postgresql.entities.Teacher              ;              import              org.springframework.stereotype.Service              ;              signification              org.springframework.transaction.note.Transactional              ;              moment              javax.annotation.PostConstruct              ;              @Service              public              class              DataFillerService              {              private              final              CourseDAO              courseDAO              ;              private              final              TeacherDAO              teacherDAO              ;              semipublic              DataFillerService              (              CourseDAO              courseDAO              ,              TeacherDAO              teacherDAO              )              {              this              .              courseDAO              =              courseDAO              ;              this              .              teacherDAO              =              teacherDAO              ;              }              @PostConstruct              @Transactional              public              void              fillData              (){              Teacher              pj              =              new              Instructor              (              "Professor Jirafales"              ,              "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Ruben2017.jpg/245px-Ruben2017.jpg"              ,              "jirafales@yahoo_.com"              );              Teacher              px              =              new              Teacher              (              "Professor X"              ,              "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS9uI1Cb-nQ2uJOph4_t96KRvLSMjczAKnHLJYi1nqWXagvqWc4"              ,              "director@xproject_.com"              );              teacherDAO              .              save              (              pj              );              teacherDAO              .              salve              (              post exchange              );              // create courses              Row              math              =              new              Course              (              "Mathematics"              ,              20              ,              (              momentaneous              )              10              ,              pj              );              Course              spanish              =              sunrise              Course              (              "Spanish"              ,              20              ,              (              short              )              10              ,              pj              );              Course              dealingWithUnknown              =              new              Course              (              "Dealing with nameless"              ,              10              ,              (              curtal              )              100              ,              pj              );              Course              handlingYourMentalPower              =              new              Course              (              "Handling your mental power"              ,              50              ,              (              forgetful              )              100              ,              pj              );              Course              introductionToPsychology              =              new              Course              (              "Presentation to psychological science"              ,              90              ,              (              short              )              100              ,              pj              );              courseDAO              .              save              (              math              );              courseDAO              .              save              (              European nation              );              courseDAO              .              save              (              dealingWithUnknown              );              courseDAO              .              save              (              handlingYourMentalPower              );              courseDAO              .              save              (              introductionToPsychology              );              }              }                      

The method acting fillData is automatically named by Outflow Context as soon the practical application circumstance finishes loading. IT uses the @Transaction annotations to indicate the smooth method acting moldiness run interior a transaction. That elbow room, if some instruction fails, the whole method will be trilled back. A you tush take in, CourseDAO and TeacherDAO has some CRUD methods available.

Now, you can test if your practical application is working:

The lotion creates several REST endpoints to access your DAO's method. Essay some commands:

            draw in http://localhost:8080/courses curl http://localhost:8080/teachers                      

Good Spring Data REST with OAuth 2.0

You shouldn't expose your database social organization without proper authentication. Net ball's solve this aside creating an OAuth 2.0 Resource Server. A resource server is a service temporary in the infrastructure that has zero login page, and it is used for server-to-server communication theory. In strange words: it needs credentials but does non handle how they are acquired.

First, you'll need to add a dependency on the Okta Spring Boot starter:

                          <colony>              <groupId>com.okta.spring</groupId>              <artifactId>okta-spring-boot-starter</artifactId>              <version>1.1.0</version>              </dependency>                      

Then add a WebSecurityConfigurerAdapter to PostgresqlApplication:

                          package              com.okta.developer.postgresql              ;              import              org.springframework.iron heel.SpringApplication              ;              import              org.springframework.boot.autoconfigure.SpringBootApplication              ;              significance              org.springframework.context.annotation.Configuration              ;              importee              org.springframework.security.config.annotation.network.builders.HttpSecurity              ;              importee              org.springframework.surety.config.annotating.web.shape.WebSecurityConfigurerAdapter              ;              signification              org.springframework.transaction.annotation.EnableTransactionManagement              ;              @SpringBootApplication              @EnableTransactionManagement              public              assort              PostgresqlApplication              {              public              static              void              main              (              Twine              []              args              )              {              SpringApplication              .              run              (              PostgresqlApplication              .              class              ,              args              );              }              @Configuration              atmospheric static              class              OktaOAuth2WebSecurityConfigurerAdapter              extends              WebSecurityConfigurerAdapter              {              @Override              fortified              nullif              configure              (              HttpSecurity              http              )              throws              Exception              {              http              .              authorizeRequests              ().              anyRequest              ().              authenticated              ()              .              and              ()              .              oauth2ResourceServer              ().              jwt              ();              }              }              }                      

The OktaOAuth2WebSecurityConfigurerAdapter class defines the protection form.

  • .authorizeRequests().anyRequest().authenticated() - tells Spring Security every petition must exist authenticated.
  • .oauth2ResourceServer().jwt() - configures the covering as a Imagination Server that will allows access tokens for authorization.

Finally, summate 2 new properties in your covering.properties file:

                          okta.oauth2.issuer              =                                                https://{yourOktaDomain}                /oauth2/default              okta.oauth2.clientId              =              {yourClientId}                      

These properties are leaving to tell Spring and Okta where to see the OAuth 2.0 issuer and describe the client ID for this application…

… Issuer, node Idaho, what am I talking about?

In front you start, you'll need a free Okta developer account. Put in the Okta CLI and run okta register to sign on for a new account. If you already have an account, run okta login. Then, run okta apps create service of process. Select the default app discover, or change it every bit you see in condition.

What does the Okta Command line interface do?

The Okta CLI will create an OAuth 2.0 Service App in your Okta Org. You will find output like the following when it's finished:

              Okta application configuration has been written to: /path/to/app/.okta.env                          

Lam cat .okta.env (OR character .okta.env happening Windows) to see the issuer and credentials for your app.

                              export                                OKTA_OAUTH2_ISSUER                =                "https://dev-133337.okta.com/oauth2/default"                export                                OKTA_OAUTH2_CLIENT_ID                =                "0oab8eb55Kb9jdMIr5d6"                export                                OKTA_OAUTH2_CLIENT_SECRET                =                "NEVER-SHOW-SECRETS"                          

Your Okta domain is the first part of your issuer, before /oauth2/default.

NOTE: You can also use the Okta Admin Console to create your app. Assure Create a Service App for more information.

Copy and paste the Guest ID in to your application.properties file.

Now, start your application every bit before:

Run curl (the -v attribute will return the response headers):

                          >              curl up              -v              http://localhost:8080/courses < HTTP/1.1 401 < Set-Cookie:              JSESSIONID              =6AA0A042FB1D69CC1CB9747820FDF5E1;              Course              =/;              HttpOnly < WWW-Authenticate: Carrier < X-Content-Type-Options: nosniff < X-XSS-Protection: 1;              mode              =block < Lay away-Control: none-hoard, no-store, max-age=0, must-revalidate < Pragma: nary-cache < Expires: 0 < X-Frame-Options: DENY < Content-Length: 0 < Date: Thu, 20 Dec 2018 04:46:21 GMT                      

The server returns a 401 HTTP code, which means you are unauthorized. Now, let's create a valid token. An light way to attain a token is to generate extraordinary exploitation OpenID Connect .

First, you'll need to create a new web application in Okta to use this servicing:

Run okta apps create. Select the default app constitute, operating theatre change it as you see meet. Select Web and press Enter.

Select Other. Then, change the Airt URI to https://oidcdebugger.com/debug and use https://oidcdebugger.com for the Logout Redirect URI.

What does the Okta CLI do?

The Okta CLI will create an OIDC Web App in your Okta Org. It testament append the airt URIs you specified and grant access to the Everyone grouping. You volition see turnout like the following when it's finished:

              Okta applications programme configuration has been written to: /path/to/app/.okta.env                          

Function cat .okta.env (or type .okta.env on Windows) to see the issuer and credentials for your app.

                              export                                OKTA_OAUTH2_ISSUER                =                "https://dev-133337.okta.com/oauth2/default"                export                                OKTA_OAUTH2_CLIENT_ID                =                "0oab8eb55Kb9jdMIr5d6"                export                                OKTA_OAUTH2_CLIENT_SECRET                =                "NEVER-SHOW-SECRETS"                          

Your Okta sphere is the first part of your issuer, before /oauth2/nonremittal.

Bank note: You can also manipulation the Okta Admin Solace to create your app. See Create a Web App for more information.

An easy way to get an access token is to generate one using OpenID Connect Debugger. First, you mustiness configure your application on Okta to use OpenID Connect's implicit flow.

Run okta login and open the ensuant URL in your web browser. Run low to the Applications section and quality the application you just created. Edit its General Settings and minimal brain dysfunction Implicit (Hybrid) as an allowed grant eccentric, with access token enabled. Then, make sure it has https://oidcdebugger.com/debug in its Login redirect URIs. Click Save and copy the client ID for the next step.

Instantly, navigate to the OpenID Join Debugger website. Substitute your customer I.D., and use https://{yourOktaDomain} /oauth2/default/v1/authorize for the Authorize URI. The say field must be filled but can contain any characters. Select token for the response type.

OpenID Connect

Submit the form to start the authentication process. You'll pick up an Okta login form if you are not logged in or you'll meet the screen below with your custom token.

Token from OpenID Connect

The token leave be valid for one hour and then you can do a great deal of testing with your API. IT's simple to enjoyment the token, just copy it and modify the curl command to use information technology every bit follows:

                          export                            Minimum              ={YOUR_TOKEN}              curl              -v              -H              "Dominance: Bearer                            ${              TOKEN              }              "              http://localhost:8080/teachers                      

Pretty sweet, eh?!

Versioning Scheme Changes in PostgreSQL with Flyway

Hole up DDL creation is a nice characteristic for PoCs or minute projects. For more significant projects that possess a complex deployment workflow and features like version rollback in case of a significant issue, the solution is non sufficient.

In that respect are various tools to handle database migrations, and matchless of the most democratic is Flyway, which works flawlessly with Spring Boot. Briefly, Migration route looks for SQL scripts on your project's resource path and runs all scripts not antecedently dead in a definite order. Flyway stores what files were executed into a particular prorogue called SCHEMA_VERSION.

Initial, add Flyway as a dependency in your pom.xml. When Spring Boot detects Migration route on the classpath, information technology will run it on startup:

                          <dependency>              <groupId>org.flywaydb</groupId>              <artifactId>migration route-core</artifactId>              </dependency>                      

By default, Flyway looks at files in the format V$X__$DESCRIPTION.sql, where $X is the migration version name, in folder src/main/resources/db/migration. Create two files: one for the DDL and another for sample information:

V1__ddl.sql

                          CREATE              TABLE              course              (              id              UUID              Non              NULL              ,              NAME              VARCHAR              (              255              ),              rate              INT2              Non              NULL              ,              workload              INT4              NOT              NULL              ,              teacher_id              UUID              ,              PRIMARY              KEY              (              id              )              );              CREATE              TABLE              teacher              (              id              UUID              Non              NULL              ,              email              VARCHAR              (              255              ),              Nominate              VARCHAR              (              255              ),              pictureurl              VARCHAR              (              255              ),              PRIMARY              KEY              (              id              )              );              ALTER              TABLE              course              ADD              Restraint              fk_course_teacher              FOREIGN              KEY              (              teacher_id              )              REFERENCES              teacher              ;                      

V2__data.sql

                          Cut-in              INTO              teacher              (              id              ,              electronic mail              ,              NAME              ,              pictureurl              )              VALUES              (              '531e4cdd-bb78-4769-a0c7-cb948a9f1238'              ,              'jirafales@yahoo_.com'              ,              'Profesor Jirafales'              ,              'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Ruben2017.jpg/245px-Ruben2017.jpg'              );              INSERT              INTO              instructor              (              id              ,              email              ,              NAME              ,              pictureurl              )              VALUES              (              '6924b3ad-a7e7-4a9a-8773-58f89ef88509'              ,              'director@xproject_.com'              ,              'Professor X'              ,              'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS9uI1Cb-nQ2uJOph4_t96KRvLSMjczAKnHLJYi1nqWXagvqWc4'              );              INSERT              INTO              course              (              id              ,              NAME              ,              rate              ,              teacher_id              ,              workload              )              VALUES              (              'aeebbc96-52be-43fa-8c01-61b9fbca8fd7'              ,              'Mathematics'              ,              10              ,              '531e4cdd-bb78-4769-a0c7-cb948a9f1238'              ,              20              );              INSERT              INTO              course              (              id              ,              Call              ,              value              ,              teacher_id              ,              workload              )              VALUES              (              'a6e54dad-a5a6-46c6-92b0-d61a78abb142'              ,              'European nation'              ,              10              ,              '531e4cdd-bb78-4769-a0c7-cb948a9f1238'              ,              1              )              ;              INSERT              INTO              course              (              Gem State              ,              NAME              ,              rate              ,              teacher_id              ,              workload              )              VALUES              (              '13710917-7469-4bd7-91cc-af8df36213c9'              ,              'Dealing with unknown'              ,              100              ,              '6924b3ad-a7e7-4a9a-8773-58f89ef88509'              ,              10              )              ;              INSERT              INTO              course              (              id              ,              Discover              ,              rate              ,              teacher_id              ,              workload              )              VALUES              (              'c5e24451-86d3-4f20-ae06-55810c3cf350'              ,              'Handling your psychogenic power'              ,              50              ,              '6924b3ad-a7e7-4a9a-8773-58f89ef88509'              ,              1000              )              ;              INSERT              INTO              track              (              id              ,              NAME              ,              rate              ,              teacher_id              ,              workload              )              VALUES              (              'd5063295-f1f6-44d3-8e3a-5ba5d8fb46eb'              ,              'Introduction to psychology'              ,              100              ,              '6924b3ad-a7e7-4a9a-8773-58f89ef88509'              ,              90              );                      

Ahead protrusive the project again, delete the class DataFillerService since these SQL files will now import all data.

In lotion.properties change the ddl-motorcar conformation to validate:

                          spring.jpa.hole up.ddl-auto              =              validate                      

This causes Hibernate to validate the schema to see if it matches with what's defined in Java. If no match is found, the application will not start.

Delete and make up a recent PostgreSQL database instance, since the first instance was created using JPA.

            stevedore              rm              -f              dev-postgres docker run              --name              dev-postgres              -p              5432:5432              -e              POSTGRES_PASSWORD              =mysecretpassword              -d              postgres:11 dock worker              White House              dev-postgres psql              -U              postgres              -c              "CREATE DATABASE coursedb"              postgres                      

Now, start Spring Boot once again:

You will go steady the same data open, but if you get a load into the logs, will placard Flyway runs the database migration:

            2018-11-25 23:50:12.941  Information 30256 --- [           main] o.f.core.intrinsical.command.DbValidate     : Successfully valid 2 migrations (execution of instrument time 00:00.037s) 2018-11-25 23:50:12.960  INFO 30256 --- [           principal] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table: "public"."flyway_schema_history" 2018-11-25 23:50:13.010  INFO 30256 --- [           main] o.f.nitty-gritty.internal.control.DbMigrate      : Contemporary variant of schema "public": << Barren Outline >> 2018-11-25 23:50:13.013  INFO 30256 --- [           of import] o.f.core group.internal.command.DbMigrate      : Migrating schema "populace" to translation 1 - ddl 2018-11-25 23:50:13.046  INFO 30256 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema "public" to version 2 - data 2018-11-25 23:50:13.066  INFO 30256 --- [           main] o.f.core.internal.instruction.DbMigrate      : Successfully applied 2 migrations to schema "public" (execution time 00:00.109s)                      

Scratch the NoSQL Show u with Spring Boot and PostgreSQL's JSONB Information Construction

NoSQL databases are, as the distinguish says, databases that do not store their data with relationships. There are many types of NoSQL databases: graph databases, key-value stores, document, etc. Generally talking, one of the most significant advantages of this sort of database is the lack of outline enforcement (you can conflate a different sort of information), different levels of data body and better performance in just about cases.

PostgreSQL adopted approximately data types to handle JSON data exclusive its information structures. This datatype is called JSONB, and this part shows how information technology is thinkable to economic consumption IT with Spring Boot and without changing your current schema.

First, create a recently migration file V3__teacher_reviews.sql.

                          Vary              Defer              instructor              ADD              COLUMN              reviews              jsonb                      

To properly exploit with this custom datatype, you need to add a habituation that right handles information technology. Add the undermentioned to pom.xml:

                          <addiction>              <groupId>com.vladmihalcea</groupId>              <artifactId>hibernate-types-52</artifactId>              <version>2.3.4</version>              </dependency>                      

The column reviews stores a JSON raiment with all reviews a instructor received. First, you need to switch the superclass to define the new datatype correctly:

EntityWithUUID.java

                          import              com.vladmihalcea.hole up.type.json.JsonBinaryType              ;              import              org.hibernate.annotations.Type              ;              import              org.hibernate.annotations.TypeDef              ;              signification              org.hibernate.annotations.TypeDefs              ;              signification              javax.persistence.Id              ;              import              javax.persistence.MappedSuperclass              ;              importee              java.util.UUID              ;              @MappedSuperclass              @TypeDefs              ({              @TypeDef              (              name              =              "jsonb"              ,              typeClass              =              JsonBinaryType              .              class              )              })              public              class              EntityWithUUID              {              @I.D.              @Type              (              type              =              "pg-uuid"              )              confidential              UUID              id              ;              public              EntityWithUUID              ()              {              this              .              id              =              UUID              .              randomUUID              ();              }              }                      

Now, create a division called Review in the entities package:

                          software program              com.okta.developer.postgresql.entities              ;              import              lombok.AllArgsConstructor              ;              import              lombok.Data              ;              import              lombok.NoArgsConstructor              ;              import              java.io.Serializable              ;              import              java.fourth dimension.LocalDate              ;              @Data              @AllArgsConstructor              @NoArgsConstructor              public              class              Review              implements              Serializable              {              private              Drawstring              author              ;              private              String              limited review              ;              private              LocalDate              date              ;              }                      

This class needs to implement Serializable As it is stored in JSON format. Right away, change Teacher class to have a reviews property:

                          import              lombok.AllArgsConstructor              ;              import              lombok.Information              ;              import              lombok.NoArgsConstructor              ;              import              org.hibernate.annotations.Eccentric              ;              importation              javax.persistence.Underlying              ;              import              javax.perseverance.Column              ;              signification              javax.persistence.Entity              ;              import              javax.persistence.FetchType              ;              import              java.util.List              ;              @Entity              @Data              @AllArgsConstructor              @NoArgsConstructor              in the public eye              class              Teacher              extends              EntityWithUUID              {              private              String along              name              ;              close              String              pictureURL              ;              head-to-head              Thread              electronic mail              ;              @Type              (              eccentric              =              "jsonb"              )              @Column              (              columnDefinition              =              "jsonb"              )              @Basic              (              fetch              =              FetchType              .              LAZY              )              toffee-nosed              List              <              Refresh              >              reviews              ;              }                      

Now you have set a name of information type jsonb but also added a fetch = LAZY property. The property tells Hole up NOT to retrieve the attribute value unless asked. Without the property, every call to a instructor instance will appendage JSON and create review objects. Hibernate necessarily a Maven plugin to work with lazy attributes properly. Edit the pommy.xml file and hyperkinetic syndrome the following snippet in the <plugins> section.

                          <plugin>              <groupId>org.hibernate.orm.tooling</groupId>              <artifactId>hole up-heighten-maven-plugin</artifactId>              <version>5.4.1.Final</version>              <executions>              <execution>              <configuration>              <failOnError>true</failOnError>              <enableLazyInitialization>honorable</enableLazyInitialization>              </configuration>              <goals>              <goal>enhance</goal>              </goals>              </murder>              </executions>              </plugin>                      

OK, you are almost in that location. You just pauperism to add some methods to add reviews to a teacher. I distinct to take a Thomas More MVC approach here and make up a Service and a Controller.

TeacherService.Java

                          computer software              com.okta.developer.postgresql.service              ;              import              com.okta.developer.postgresql.entities.Review              ;              signification              javax.validation.constraints.NotNull              ;              public              interface              TeacherService              {              /**      *      * @param teacherID      * @param review      * @throws javax.persistence.EntityNotFoundException      */              void              addReview              (              @NotNull              String              teacherID              ,              @NotNull              Review              reappraisal              );              }                      

SimpleTeacherService.java

                          software              com.okta.developer.postgresql.service              ;              import              com.okta.developer.postgresql.dao.TeacherDAO              ;              signification              com.okta.developer.postgresql.entities.Review              ;              import              com.okta.developer.postgresql.entities.Teacher              ;              moment              org.springframework.stereotype.Service              ;              import              org.springframework.dealing.annotation.Isolation              ;              import              org.springframework.transaction.annotation.Transactional              ;              import              javax.doggedness.EntityNotFoundException              ;              import              Java.time.LocalDate              ;              import              java.util.ArrayList              ;              import              java.util.Objects              ;              import              java.util.UUID              ;              @Serving              public              classify              SimpleTeacherService              implements              TeacherService              {              snobbish              final              TeacherDAO              teacherDAO              ;              public              SimpleTeacherService              (              TeacherDAO              teacherDAO              )              {              this              .              teacherDAO              =              teacherDAO              ;              }              @Override              @Transactional              (              isolation              =              Closing off              .              SERIALIZABLE              )              public              invalidate              addReview              (              String              teacherID              ,              Brush up              survey              )              {              Objects              .              requireNonNull              (              teacherID              );              Objects              .              requireNonNull              (              review              );              Teacher              instructor              =              teacherDAO              .              findById              (              UUID              .              fromString              (              teacherID              ))              .              orElseThrow              (()              ->              new              EntityNotFoundException              (              teacherID              ));              reexaminatio              .              setDate              (              LocalDate              .              now              ());              if              (              teacher              .              getReviews              ()              ==              null              ){              instructor              .              setReviews              (              new              ArrayList              <>());              }              teacher              .              getReviews              ().              add              (              review              );              teacherDAO              .              save              (              instructor              );              }              }                      

TeacherController.coffee

                          software system              com.okta.developer.postgresql.controllers              ;              import              com.okta.developer.postgresql.entities.Review              ;              import              com.okta.developer.postgresql.service.TeacherService              ;              import              org.springframework.HTTP.ResponseEntity              ;              import              org.springframework.vane.bind.annotation.*              ;              import              javax.perseverance.EntityNotFoundException              ;              @RestController              unexclusive              sort out              TeacherController              {              individual              final              TeacherService              teacherService              ;              public              TeacherController              (              TeacherService              teacherService              )              {              this              .              teacherService              =              teacherService              ;              }              @PostMapping              (              "/teachers/{id}/review"              )              public              ResponseEntity              addReview              (              @RequestBody              Review              review              ,              @PathVariable              (              "id"              )              String              teacherID              ){              sample              {              teacherService              .              addReview              (              teacherID              ,              recap              );              restitution              ResponseEntity              .              ok              ().              build              ();              }              catch              (              EntityNotFoundException              e              ){              return              ResponseEntity              .              notFound              ().              build              ();              }              }              }                      

In SimpleTeacherService, note that there is an annotation @Transactional(isolation = Isolation.SERIALIZABLE). This means every call to this method runs in the most covert transaction level. In separate actor's line, once the code reads the reviews JSON value, no some other code can read operating room publish on the reviews column (it is blocked) until the transaction finishes. Why's that? Since you are manipulating JSON happy if a co-occurrent dealings updates the pillar, one of them will have consistency problems.

You can now start your app:

And test the review upload away running Gyre:

            curl              -X              POST              \              -H              "Authorization: Bearer                            $TOKEN              "              \              HTTP://localhost:8080/teachers/531e4cdd-bb78-4769-a0c7-cb948a9f1238/review              \              -H              'Content-Case: application/json'              \              -d              '{     "author" : "Raphael",     "review" : "Test"   }'                      

Learn Many almost Leap Boot, PostgreSQL, Hibernate, JPA, and Spring Data REST

In this tutorial, you lettered how to mix Spring Boot with PostgreSQL and expend some civilised technologies like Migration route and JSONB. You can find the source code for this blog Emily Price Post on GitHub.

There is plenty more to learn some JPA, Hole up and PostgreSQL. Delight refer to the following posts if you'rhenium fascinated in more knowledge:

  • Produce a Secure Leaping REST API
  • Build a Basic App with Spring Boot and JPA using PostgreSQL
  • Use React and Spring Boot to Build a Shield-shaped CRUD App
  • Build a Basic CRUD App with Angular 7.0 and Recoil Boot 2.1
  • NoSQL Options for Coffee Developers

Like what you learned today? Comply us on Chitter, and subscribe to our YouTube conduct for more awesome content!

Two Almost Identical Methods Where One Works and One Returns Stack Overflow Error

Source: https://developer.okta.com/blog/2019/02/20/spring-boot-with-postgresql-flyway-jsonb

0 Response to "Two Almost Identical Methods Where One Works and One Returns Stack Overflow Error"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel