Data with JPAExtra· 45 min read

Connecting to a Real Database (MySQL/PostgreSQL)

H2 is great for learning, but real jobs store data in a real database like MySQL or PostgreSQL — here is exactly how to wire one up.

What you will learn

  • Swap H2 for a real MySQL or PostgreSQL database
  • Configure the datasource in application.properties
  • Understand the ddl-auto setting

Why move off H2?

Until now you used H2, an in-memory database — it lives in the computer’s memory while the app runs and is wiped every time the app restarts. That is perfect for learning, but useless for a real app: your users’ data would vanish on every restart.

Real back-ends use a persistent database — one that stores data on disk so it survives restarts. The two most common in Java jobs are MySQL and PostgreSQL (often shortened to “Postgres”). The good news: because you used JPA, your entities and repositories do not change at all — you only swap the database underneath.

The switch, in three steps

Moving from H2 to a real database is the same three steps for either MySQL or PostgreSQL. Here is the whole flow before we do each part:

  1. Have the database running and create an empty database (schema) for your app to use.
  2. Add the database driver to pom.xml — a small library that lets Java talk to that specific database.
  3. Point Spring at it in application.properties with a URL, username and password (the “datasource” settings).

Step 1: create an empty database

Install MySQL or PostgreSQL (or run one in Docker), then make one empty database for your app. In MySQL’s command line that is a single command:

SQL: create an empty database for the app
CREATE DATABASE codingclave;

Note: Output: Query OK, 1 row affected You now have an empty database named codingclave. JPA will create the tables inside it for you — you do not write CREATE TABLE by hand.

Step 2: add the driver

A driver is the library that lets Java connect to one particular database. Replace the H2 dependency with the right driver. For MySQL:

pom.xml: the MySQL driver
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

Note: Output: (No output — this adds the MySQL driver so Java can speak to a MySQL server. For PostgreSQL you would instead add the org.postgresql:postgresql dependency.)

Step 3: point Spring at the database

In src/main/resources/application.properties you give Spring the datasource details — where the database is, and how to log in. A datasource is simply the connection settings to a database.

application.properties: MySQL datasource and JPA settings
# Where the database is, and which one to use
spring.datasource.url=jdbc:mysql://localhost:3306/codingclave
spring.datasource.username=root
spring.datasource.password=your_password

# Let Hibernate create/update the tables from your entities
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Note: Output: On startup Spring connects to MySQL and (because ddl-auto=update) creates or updates the tables to match your entities. With show-sql=true you also see the SQL it runs, e.g.: Hibernate: create table product (id bigint not null auto_increment, name varchar(255), price float(53), primary key (id)) Your data now lives in MySQL and survives restarts.

Reading the URL jdbc:mysql://localhost:3306/codingclave piece by piece: jdbc is Java’s standard way to talk to databases; mysql is the database type; localhost:3306 is the address and port the database listens on (3306 is MySQL’s default); codingclave is the database you created in Step 1.

The ddl-auto setting

spring.jpa.hibernate.ddl-auto controls how Hibernate (the engine JPA uses under the hood) manages your tables. Know these four values:

ValueWhat it doesUse when
noneTouch nothing — you manage tables yourselfProduction (safest)
validateOnly check entities match existing tablesProduction with managed schema
updateAdd new tables/columns to match entitiesDevelopment
create-dropDrop and recreate tables each runQuick tests only

Tip: Keep secrets like the database password out of your code. In real projects you read them from environment variables, e.g. spring.datasource.password=${DB_PASSWORD} — Spring fills in the value from the environment so the password never sits in your committed files.

Watch out: Never use ddl-auto=update or create-drop on a production database. update can make surprising schema changes, and create-drop deletes all your data on every restart. In production use none or validate and manage the schema with migration tools.

Q. You move from H2 to MySQL. What must change in your @Entity classes and JpaRepository interfaces?

Answer: Because JPA sits between your code and the database, your entities and repositories stay the same. You only add the right driver and set the datasource URL, username, password and ddl-auto for the new database.

✍️ Practice

  1. Add the MySQL (or PostgreSQL) driver and set the datasource URL, username and password in application.properties.
  2. Run your CRUD app, insert a record, restart the app, and confirm the record is still there.

🏠 Homework

  1. Point your Task or Product API at a real MySQL/Postgres database, set ddl-auto=update, and verify data survives a restart. Note the four ddl-auto values and when to use each.
Want to learn this with a mentor?

CodingClave runs guided, project-based training (28-day, 45-day & 6-month batches).

Explore Training →