1. Structure of a Spring Boot Project
The typical structure of a Spring Boot project looks like this:

Explanations of the Structure:
- src/main/java: This is where all the Java code resides.
- com/example: The base package name, usually reflecting the company’s domain name.
- controller/: Contains the REST controllers that handle HTTP requests.
- service/: Business logic is implemented here.
- repository/: Data access objects that interact with the database.
- Application.java: The main application class that contains the
main
method and starts Spring Boot. - src/main/resources: This is where resources like configuration files and static files are located.
- application.properties: Configuration file for Spring Boot.
- static/: Static resources like CSS, JS, and images.
- templates/: Templates for rendering views (e.g., Thymeleaf).
- src/test/java: This is where the tests for the application are located.
- pom.xml: Maven project file that defines dependencies and plugins.
2. AOP Concepts (Aspect-Oriented Programming)
AOP allows you to separate cross-cutting concerns like logging, transactions, and security from business logic. Important terms include:
- Aspect: A modular unit of cross-cutting logic.
- Join Point: A specific point in the program flow where an aspect can be applied.
- Advice: The code that is executed at a Join Point.
- Pointcut: An expression that defines the Join Points where Advice is applied.
Example:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBeforeMethod() {
System.out.println("A method is being called.");
}
}
3. Database Access in Spring Boot
JDBC Template Example
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public Map<String, Object> getUserById(int id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForMap(sql, id);
}
public List<Map<String, Object>> getAllUsers() {
String sql = "SELECT * FROM users";
return jdbcTemplate.queryForList(sql);
}
}
Difference between queryForMap
and queryForList
queryForMap
: Returns a single row as aMap
, using column names as keys.queryForList
: Returns a list of rows, with each row represented as aMap
.
JdbcTemplate
supports batch processing, which allows us to execute multiple SQL statements in a single batch. This can significantly improve performance when inserting or updating large amounts of
public void batchAddUsers(List<User> users) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, users.get(i).getName());
ps.setString(2, users.get(i).getEmail());
}
@Override
public int getBatchSize() {
return users.size();
}
});
}
To convert rows of the result set into custom objects, we can implement the RowMapper
interface. This is especially useful for queries that return multiple rows.
public List<User> getAllUsers() {
String sql = "SELECT * FROM users";
return jdbcTemplate.query(sql, new UserRowMapper());
}
When performing multiple operations that need to be executed as a single unit of work, we can manage transactions using Spring’s @Transactional
annotation.
@Transactional
public void createUserAndProfile(User user, Profile profile) {
addUser(user.getName(), user.getEmail());
// Insert profile logic here
}
4. Spring Data JDBC
Spring Data JDBC is a part of the Spring Data project that provides a simplified way to access relational databases using plain JDBC. It focuses on a more straightforward approach to data access by leveraging the concepts of repositories and entities, while maintaining a close relationship with the underlying database.
Key Features of Spring Data JDBC:
- Entity Mapping: Maps Java objects directly to database tables without the complexity of ORM (Object-Relational Mapping).
- Repository Support: Provides a repository abstraction, allowing you to perform CRUD operations without writing boilerplate code.
- Simplicity: Offers a simpler programming model compared to JPA, making it easier to understand and use for straightforward use cases.
Here’s a simple example of using Spring Data JDBC:
import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.mapping.Table;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Table("users")
public class User {
@Id
private Long id;
private String name;
private String email;
// Getters and Setters
}
@Repository
public interface UserRepository extends CrudRepository<User, Long> {
List<User> findByName(String name);
}
In this example:
- The
User
class represents a table in the database, with fields mapped to columns. - The
UserRepository
interface extendsCrudRepository
, providing methods to perform CRUD operations without additional implementation.
5. Spring Data JPA
What is JPA?
Java Persistence API (JPA) is a specification for managing relational data in Java applications. Spring Data JPA simplifies the implementation of JPA-based repositories.
Concrete Example
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
List<User> findByLastName(String lastName);
}
Dynamic Finder Methods (supported keywords)
findBy
: Searches by a specific attribute.findByFirstNameAndLastName
: Searches by multiple attributes.findByAgeGreaterThan
: Searches for values greater than a specific value.
Advantages of JPA
- Simplicity: Less boilerplate code compared to JDBC.
- Abstraction: Hides the complexity of database interaction.
- Flexibility: Supports different databases without changes to the code.
5. Comparison: JDBC, JdbcTemplate, and JPA
Feature | JDBC | JdbcTemplate | JPA |
---|---|---|---|
Level of Abstraction | Low (direct database interaction) | Medium (simplifies JDBC operations) | High (object-oriented data access) |
Ease of Use | Requires boilerplate code for CRUD | Reduces boilerplate with utility methods | Uses annotations and repositories for simplicity |
Error Handling | Manual exception handling | Automatic translation to Spring exceptions | Automatic handling of persistence exceptions |
Transaction Management | Manual management required | Supports transaction management with Spring | Built-in transaction handling with @Transactional |
Performance | High (direct access) | High (optimized for batch operations) | Generally lower due to additional overhead of ORM |
Mapping | Manual mapping of result sets to objects | Supports RowMapper for custom mapping | Automatic mapping of entities to database tables |
Use Cases | Suitable for simple, performance-critical applications | Good for straightforward JDBC operations | Best for complex applications requiring rich domain models |
Fazit
- JDBC is suitable for low-level database access where performance is critical, but it requires a lot of boilerplate code.
- JdbcTemplate simplifies JDBC usage by handling resource management and providing utility methods, making it easier to work with databases.
- JPA is ideal for applications that require complex object-relational mapping and a higher level of abstraction, but it comes with additional overhead.
Choosing between these options depends on the specific requirements of our application, including complexity, performance, and ease of use.
6. Transactions in Spring
Spring provides support for declarative transactions, allowing us to manage transactions through annotations.
Example of Transactions
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void createUser(User user) {
userRepository.save(user);
// Additional operations that are part of the transaction
}
}
Conclusion
This tutorial gives us an overview of the structure of a Spring Boot project, AOP, database access, Spring Data JPA, and transactions.