A simple data class that represents a customer from the database. Uses a Java record to avoid writing boilerplate code.
A domain model is a class that represents data in your application. Instead of passing around raw database values, we create a Customer object that holds the id, first name, and last name together.
A record is a special Java class (added in Java 14) that automatically generates code for you.
Without a record, you'd have to write:
public class Customer {
private final long id;
private final String firstName;
private final String lastName;
// Constructor
public Customer(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
// Getters
public long id() { return id; }
public String firstName() { return firstName; }
public String lastName() { return lastName; }
// equals(), hashCode(), toString() - even more code!
}With a record, one line does all of that:
public record Customer(long id, String firstName, String lastName) { }What the record gives you automatically:
- Constructor that takes all fields
- Getter methods:
id(),firstName(),lastName() equals()- compares all fieldshashCode()- generates hash from all fieldstoString()- prints all field values
@Override is an annotation that tells the compiler: "I'm replacing a method that exists in the parent class."
@Override
public String toString() {
// my custom version
}Why use it?
- The compiler checks that you're actually overriding something
- If you make a typo (like
tostring()instead oftoString()), the compiler catches it - Makes code clearer - you can see this method replaces an inherited one
Records give you a default toString() that looks like:
Customer[id=3, firstName=Josh, lastName=Bloch]
But the guide overrides it to use a custom format:
Customer[id=3, firstName='Josh', lastName='Bloch']
The custom version adds quotes around the string values. This is a style choice - you might want different formatting for logging or debugging.
String.format() creates a string by filling in placeholders with values.
String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName)The placeholders:
%d= decimal number (forlong,int)%s= string (forStringand most objects)
How it works:
- First
%dgets replaced withid - First
%sgets replaced withfirstName - Second
%sgets replaced withlastName
Example:
String.format("Hello %s, you are %d years old", "Alice", 25)
// Result: "Hello Alice, you are 25 years old"public record Customer(long id, String firstName, String lastName) {
@Override
public String toString() {
return String.format(
"Customer[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
}Line by line:
public record Customer(...)- defines a record with three fields@Override- we're replacing the default toString()public String toString()- method that returns a string representationString.format(...)- creates the formatted string- The format string with
%dand%splaceholders id, firstName, lastName- values that fill the placeholders
| Record Field | DB Column | Type |
|---|---|---|
id |
id |
long |
firstName |
first_name |
String |
lastName |
last_name |
String |
Note: Java uses camelCase (firstName), databases typically use snake_case (first_name). The RowMapper handles this translation.
(rs, rowNum) -> new Customer(
rs.getLong("id"),
rs.getString("first_name"),
rs.getString("last_name")
)This lambda converts each database row into a Customer object:
rs= ResultSet (the current row from the database)rowNum= which row number (we don't use it here)rs.getLong("id")= get theidcolumn as a longrs.getString("first_name")= get thefirst_namecolumn as a String
- JdbcTemplate - Uses Customer with RowMapper
- Java Records - Language feature