In this section, you will learn how to interact with databases using Spring. If you have worked with JDBC, you will likely agree that it is not the most elegant code. It typically requires lots of boilerplate for even the most basic database operations, making the process quite tedious.
That's where Spring Data comes in!
What is Spring Data?
Spring Data offers a package of solutions to reduce your workload. By utilizing Spring Data, you can significantly reduce the effort required to perform database operations, making your work more efficient and enjoyable.
As you may recall, the Spring Framework is sometimes called a framework of frameworks. The same holds true for Spring Data. Many submodules help to give Spring Data its proper functionality. For example, Spring Data includes the following modules:
-
Spring Data JDBC - Provides Spring JDBC support. Making manual querying of the DB more convenient.
-
Spring Data JPA - Provides convenient configuration of and entry to the DB using models and repositories. This technology is widely accepted in enterprise software development because it simplifies how you interact with databases. The majority of this section will focus on this module.
-
Spring Data REST - Facilitates exporting data/objects as hypermedia-driven RESTful resources. In simpler terms, Spring Data also helps translate between Java and internet-speak. The course will cover this translation functionality in more detail in the HTTP & Web Services section.
These Spring Data modules (and others) were not built from scratch. The exact opposite is true. The Spring Data creators decided they would not create their own out-of-the-box solution. Instead, they built an abstraction layer on top of existing projects, giving you new ways of interacting with the existing tools.
Take Spring Data JPA. By crafting an extra layer over an existing system named Hibernate, Spring Data JPA added additional features for you to interact with. These extra features are so helpful you rarely need to interact with Hibernate directly anymore.
How Spring Data Makes Life Easier
The following three code examples illustrate how drastically Spring Data can reduce your workload. Keep in mind that you are not expected to understand what's happening here. You'll learn how this works throughout this section.
For now, know Spring Data lets you go from this:
public class PlainJDBCExample {
public static void main(String[] args) {
Connection dbConnection = null;
Statement statement = null;
try {
Class.forName("com.mysql.jdbc.Driver");
dbConnection = DriverManager.getConnection(
"URL", "username", "password");
statement = dbConnection.createStatement();
String customQuery = "SELECT * FROM employees";
ResultSet rs = statement.executeQuery(customQuery);
while (rs.next()) {
System.out.println(new Employee(
rs.getInt("id"),
rs.getString("first_name"),
rs.getString("last_name")));
}
rs.close();
statement.close();
dbConnection.close();
} catch (Exception e1) {
e1.printStackTrace();
} finally {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e2) {
e2.printStackTrace();
}
try {
if (dbConnection != null) {
dbConnection.close();
}
} catch (SQLException e3) {
e3.printStackTrace();
}
}
}
}
@Data
@AllArgsConstructor
class Employee {
private int id;
private String firstName;
private String lastName;
}
To this:
@SpringBootApplication
public class SpringDataJDBCExample implements CommandLineRunner {
@Autowired
private JdbcTemplate template;
public static void main(String[] args) {
SpringApplication.run(SpringDataJDBCExample.class, args);
}
@Override
public void run(String... args) throws Exception {
template.query("SELECT * FROM employees", new Object[]{},
(rs, rowNum) -> new Employee(
rs.getInt("id"),
rs.getString("first_name"),
rs.getString("last_name")
)
).forEach(employee -> System.out.println(employee.toString()));
}
}
@Data
@AllArgsConstructor
class Employee {
private int id;
private String firstName;
private String lastName;
}
To this:
@SpringBootApplication
public class SpringDataJPAExample implements CommandLineRunner {
@Autowired
EmployeeRepository employeeRepository;
public static void main(String[] args) {
SpringApplication.run(SpringDataJPAExample.class, args);
}
@Override
public void run(String... args) {
employeeRepository.findAll()
.forEach(employee ->
System.out.println(employee.toString()));
}
}
@Entity
@Data
@ToString
class Employee {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
}
@Repository
interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
Notice how this last example doesn't have a single explicit database operation detail. No SQL. No looping through returned rows. No hard-coded column names. No manual mapping of results to Java objects. It almost feels like cheating!
Configuring Spring Data
While these examples demonstrate code progression afforded by Spring Data integration, they aren't meant to be run without additional configuration. Moving forward, most of the examples and sub-projects in your labs project will require database access.
Please complete the following steps:
Info: If you have previously completed the Java 301 course and already have a schema named codingnomads, skip to step 2.
Also, please note that you will not ordinarily use the root user in this manner. Best practice dictates you create a new database user (or multiple users) for each project, whose privileges are dialed back to match the requirements. The root account should stay safe and secure and only be used when absolutely necessary!
-
Using MySQLWorkbench or the CLI, create a new empty schema called codingnomads.
-
Now to configure Spring Data inside your labs project, open up your application.properties file and navigate to the following lines:
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:mysql://localhost:3306/codingnomads?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
spring.datasource.username=root
# please enter your password below - be sure not to push your password to GitHub
spring.datasource.password=YOUR_MYSQL_PASSWORD_HERE
- Enter your root MySQL password where specified. These properties are essential in allowing Spring Data to take over much of the boilerplate work. Chiefly, Spring Data will use the URL, username, and password properties to open a database connection for you.
Alert: When storing your MySQL root password in plain text, do not push it to GitHub! For a more secure approach, look into storing the password in an environment variable, which can be accessed in your properties file like this: spring.datasource.password=${ENV_VARIABLE}
Summary: Spring Data
Spring Data is useful for many reasons, including:
- Helps reduce boilerplate code associated with database operations.
- Provides abstractions that unlock new ways to interact with existing tools.
- Leverages existing libraries while providing a decoupled approach.
- Abstracts away almost all manual database interaction.
Spring Data includes several handy modules, including the following:
- Spring Data JDBC - Provides Spring JDBC support. Making manual querying of the DB more convenient.
- Spring Data JPA - Provides convenient configuration of and entry to the DB using models and repositories.
- Spring Data REST - Facilitates exporting data/objects as hypermedia-driven RESTful resources.