4 Database tips for Java Developers 💡

Joao Marques - Jul 8 - - Dev Community

Introduction

🔍 Understanding databases is essential for Java developers, as they frequently handle critical data such as user information, past actions, application settings, and feature flags. As applications expand, databases must scale to meet performance demands and ensure efficient data management. For insights into scaling databases effectively, refer to my article on optimizing bank data growth with sharding architecture.

🚀 Drawing from my experience, I've wrote 4 essential tips to enhance your database practices in Java.

1. Always use an ORM Framework (Please do that, think about your future dev colleagues 😅)

💡 Why: ORM frameworks like Hibernate or JPA help manage database interactions efficiently, reducing boilerplate code and they manage the protection for SQL injections.
Trust me, big applications without orm are very hard to maintain and takes more time than you think to manage simple things.

💻 Example: Using Hibernate with JPA annotations.


import javax.persistence.*;

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "username", nullable = false, unique = true)
    private String username;

    @Column(name = "email", nullable = false, unique = true)
    private String email;

    // Getters and Setters (I'd ratter use lombok)
}
Enter fullscreen mode Exit fullscreen mode

Repository:

// Repository class using Spring Data JPA
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}
Enter fullscreen mode Exit fullscreen mode

2. Validate Input Data

💡 Why: Validating data ensures that only correct and expected data is stored, preventing corruption and errors.
Make sure your services are ready catch exceptions coming from the database.

💻 Example: Using Hibernate Validator.


import javax.validation.constraints.*;

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Size(min = 5, max = 15)
    private String username;

    @NotNull
    @Email
    private String email;

    // Getters and Setters (I'd ratter use lombok)
}
Enter fullscreen mode Exit fullscreen mode

3. Implement Database Transactions

💡 Why: Transactions ensure that you database transactions can always rollback in case an exception happens during thread execution.

💻 Example: Using Spring's @Transactional annotation.
In this example, in case userActivityRepository.save(activity) throws an exception userRepository.save(user) will be rolled back.


import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Transactional
    public void createUserAndSaveActivity(User user, UserActivity activity) {
        userRepository.save(user);
        userActivityRepository.save(activity);
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Monitor Queries

💡 Why: Monitoring queries can inform your team where in your application is causing the bottleneck.
The team can create jira tickets to work on the performance for those bottleneck queries.

💻 Example: Using Hibernate's statistics with the @Timed annotation from the Spring Metrics module to monitor the performance.


import org.springframework.stereotype.Repository;
import org.springframework.metrics.annotation.Timed;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

@Repository
public class UserRepository {

    // PersistenceContext was used only for example
    @PersistenceContext
    private EntityManager entityManager;

    @Timed
    public List<User> getUsersWithOptimizedQuery(String role) {
        return entityManager.createQuery("SELECT u FROM User u WHERE u.role.name = :roleName", User.class)
                            .setParameter("roleName", role)
                            .getResultList();
    }
}
Enter fullscreen mode Exit fullscreen mode

📈 Implementing these strategies are just the basis to keep your database clean and efficient when working with Java applications, that can grow anytime.

. . . . . .
Terabox Video Player