Set up dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> 

Configuring JPA and Hibernate 

in application.properties file

spring.datasource.url=jdbc:mysql://localhost:3306/dbname
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update 

or application.yml

spring:
  application:
    name: demoapp
  datasource:
    url: jdbc:mysql://localhost:3306/dbname
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    open-in-view: false 

More config (optional)

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableJpaRepositories(basePackages = "com.jamiewang.demo.dao", entityManagerFactoryRef = "primaryEntityManager", transactionManagerRef = "primaryTransactionManager")
@EnableTransactionManagement
public class HibernateConfig {
    private final Logger log = LoggerFactory.getLogger(getClass());

    private LocalContainerEntityManagerFactoryBean entityManager;

    @Value("${spring.datasource.url}")
    private String jdbcUrl;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    private DataSource dataSource;

    @Bean
    public DataSource dataSource(){
        this.dataSource = DataSourceBuilder.create()
                .url(jdbcUrl)
                .username(username)
                .password(password)
                .driverClassName(driverClassName)
                .build();
        return this.dataSource;
    }

    @Bean
    public LocalSessionFactoryBean localSessionFactoryBean(){
        Properties properties=new Properties();
        properties.setProperty("hibernate.show_sql", "true");
        properties.setProperty("hibernate.format_sql", "true");
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        LocalSessionFactoryBean lsb=new LocalSessionFactoryBean();
        lsb.setDataSource(dataSource());
        /**
         * set entity location
         */
        lsb.setPackagesToScan("com.jamiewang.demo.entity");
        lsb.setHibernateProperties(properties);
        return lsb;
    }

    @Bean
    @Primary
    LocalContainerEntityManagerFactoryBean primaryEntityManager(EntityManagerFactoryBuilder builder) {
        log.info("Scanning entity...");
        entityManager = builder.dataSource(this.dataSource).packages("com.jamiewang.usercenter.entity")
                .persistenceUnit("primaryPersistenceUnit").build();
        return entityManager;
    }

    @Bean
    @Primary
    PlatformTransactionManager primaryTransactionManager(EntityManagerFactoryBuilder builder) {
        log.info("Configuration database transaction manager...");
        return new JpaTransactionManager(entityManager.getObject());
    }

}
 

Creating Entities

@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    private String author;

    private String ISBN;

    // Getters and setters
} 

Creating Repositories

In Spring Data JPA, we can create a repository by creating an interface that extends the JpaRepository interface.

This interface will provide basic CRUD functionality for our Book entity and can be easily injected into our service layer.

public interface BookRepository extends JpaRepository<Book, Long> {
} 

Custom Queries

JPA provides a simple and convenient way to create custom queries using the @Query annotation. This annotation allows you to define a query directly in the repository interface, rather than in a separate class or XML file. The @Query annotation takes a single parameter, the query string. The query string can be written in either JPQL (Java Persistence Query Language) or SQL.

The following example shows how to use the @Query annotation to create a custom query that retrieves all users with a specific role:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.role = ?1")
    List<User> findByRole(String role);
} 

In this example, the findByRole method is annotated with the @Query annotation and the query string is written in JPQL. The ?1 parameter is a positional parameter that is replaced with the value of the role argument when the query is executed.

It’s also possible to use named parameters instead of positional parameters. Named parameters are prefixed with a : and can be used in the query string by referencing them by name. The following example shows how to use named parameters:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.role = :role")
    List<User> findByRole(@Param("role") String role);
} 

Hibernate Query Language (HQL)

HQL is an object-oriented query language that is similar to SQL, but it operates on the objects of the persistent classes rather than on the database tables. HQL is used to create queries that are executed by the Hibernate framework.

The following example shows how to use HQL to create a query that retrieves all users with a specific role:

Session session = sessionFactory.openSession();
Query query = session.createQuery("FROM User WHERE role = :role");
query.setParameter("role", "admin");
List<User> users = query.list(); 

In this example, the createQuery method is used to create a new query. The query string is written in HQL and the :role parameter is a named parameter that is replaced with the value of the role variable when the query is executed.

Using HQL can be more powerful than using JPA’s @Query annotation, as it allows you to execute more complex queries and to use advanced features of the Hibernate framework. However, it can also result in more complex codebase and harder to maintain, that’s why it’s important to use it judiciously and with caution.

Best Practices

When using custom queries and HQL in your SpringBoot application, there are a few best practices to keep in mind:

  1. Use parameter binding: Instead of concatenating variables into the query string, use parameter binding to prevent SQL injection attacks.

  2. Keep queries simple: Complex queries can be difficult to maintain and may result in poor performance. Try to keep queries as simple as possible.

  3. Use pagination: When retrieving large amounts of data, use pagination to limit the number of results returned and to improve performance.

  4. Test your queries: Always test your queries to ensure that they are returning the expected results and to check for any performance issues.

  5. Logging: Enable the logging of SQL statements to monitor the performance and identify any issues

Encapsulate your own common repository layer method

If you followed the optional config. You can also encapsulate a more powerful one like this:

import java.io.Serializable;
import java.util.List;
import java.util.Map;

public interface PrimaryDaoService {

	public <T> void save(T o);

	public <T> void delete(T o);

	public <T> void update(T o);

	public <T> T get(Class<T> c, Serializable id);

	public List<Map<String, Object>> getListBySql(String sql);

} 
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import org.example.entity.User;
import org.hibernate.query.sql.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Repository
public class PrimaryDaoServiceImpl implements PrimaryDaoService {

    @PersistenceContext(unitName = "primaryEntityManager")
    private EntityManager entityManager;


    @Override
    public <T> void save(T o) {
        if (null != o) {
            if (o instanceof User) {
                User data = (User) o;
                data.setCreateTime(new Date());
                data.setModificationTime(new Date());
                data.setCreaterId(-1l);
                data.setModifierId(-1l);
            }
            entityManager.persist(o);
        }
    }

    @Override
    public <T> void delete(T o) {
        if (null != o) {
            entityManager.remove(o);
        }
    }

    @Override
    public <T> void update(T o) {
        if (null != o) {
            entityManager.merge(o);
        }
    }

    @Override
    public <T> T get(Class<T> c, Serializable id) {
        if (null != id) {
            return (T) entityManager.find(c, id);
        }
        return null;
    }

    @Transactional(readOnly = true)
    @Override
    public List<Map<String, Object>> getListBySql(String sql) {
        Query q = entityManager.createNativeQuery(sql);
        q.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return q.getResultList();
    }

} 

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

Catalogue