Introduce EzyJPA

Updated at 1699803908000

1. Introduce EzyJPA

EzyJPA (Easy going to JPA Interaction) is a framework support to interact to JPA, It supports:
  1. Transparently map your Java entities to database record and back
  2. Query, update, delete and aggregation by query string
  3. Annotation driven

2. Structure of EzyJPA

  1. Database Context: wraps EntityManager, DataBinding. Manages repositiors, QueryManager and DataSerializers. Provides function to get repostiories, queries and serializers
  2. Repostiories: Manages all repostiores by name and type
  3. QueryManager: Manages all queries, collects queries from annotations and deverloper set
  4. DataSerializers: Manages all data serializers and deserializers, provide a way to allow deverloper custom and set their serializers and deverlopers
  5. Repostiory: converts queries, data and calls to database

3. Install JPA

1. To use EzyJPA you need add dependency

<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezydata-jpa</artifactId>
    <version>1.2.8</version>
</dependency>

The latest version can be found in the Maven Central repository. 2. To use EzyJPA you need configure to create repositories You can use ezyfox-boot-autoconfigure by add to your pom.xml:

<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezyfox-boot-autoconfigure</artifactId>
    <version>1.1.0</version>
</dependency>

Or because with some reason, you can not use ezyfox-boot-autoconfigure you can config like this:

    import com.tvd12.ezydata.database.EzyDatabaseContext;
    import com.tvd12.ezydata.jpa.EzyJpaDatabaseContextBuilder;
    import com.tvd12.ezydata.jpa.loader.EzyJpaDataSourceLoader;
    import com.tvd12.ezydata.jpa.loader.EzyJpaEntityManagerFactoryLoader;
    import com.tvd12.ezyfox.bean.EzyBeanConfig;
    import com.tvd12.ezyfox.bean.EzyPackagesToScanAware;
    import com.tvd12.ezyfox.bean.EzySingletonFactory;
    import com.tvd12.ezyfox.bean.EzySingletonFactoryAware;
    import com.tvd12.ezyfox.bean.annotation.EzyAutoBind;
    import com.tvd12.ezyfox.bean.annotation.EzyConfigurationBefore;
    import com.tvd12.ezyfox.util.EzyPropertiesAware;
    import lombok.Setter;
    import javax.persistence.EntityManagerFactory;
    import javax.sql.DataSource;
    import java.util.Properties;
    import java.util.Set;
    import static com.tvd12.ezyfox.boot.util.EzyDatabaseContexts.addRepositoriesFromDatabaseContextToSingletonFactory;
    @Setter
    @EzyConfigurationBefore
    public class EzyJpaConfiguration implements
        EzyBeanConfig,
        EzyPropertiesAware,
        EzySingletonFactoryAware {
        private Properties properties;
        @EzyAutoBind
        private EzySingletonFactory singletonFactory;
        @Override
        public void config() {
            addRepositoriesFromDatabaseContextToSingletonFactory(
                databaseContext(),
                singletonFactory
            );
        }
        private EzyDatabaseContext databaseContext() {
            return new EzyJpaDatabaseContextBuilder()
                .properties(properties)
                .entityManagerFactory(entityManagerFactory())
                .scan("your_package_to_scan")
                .build();
        }
        private EntityManagerFactory entityManagerFactory() {
            return new EzyJpaEntityManagerFactoryLoader()
                .entityPackages(packagesToScan)
                .dataSource(dataSource())
                .properties(properties)
                .load("Default");
        }
        private DataSource dataSource() {
            return new EzyJpaDataSourceLoader()
                .properties(properties, "datasource")
                .load();
        }
    }

3. You can add to your configuration file like this:

    # for application.yaml
    datasource:
      jdbcUrl: jdbc:mysql://root:12345678@localhost:3306/test
      driverClassName: com.mysql.cj.jdbc.Driver
    # for application.properties
    datasource.jdbcUrl=jdbc:mysql://root:12345678@localhost:3306/test
    datasource.driverClassName=com.mysql.cj.jdbc.Driver

4. Example

For full example you can look at ezyfox-examples Github repo Let’s say we need create an http server application to manage a book store (Category, Author and Book), we need 6 apis

  • api/v1/author/add: Add an author
  • api/v1/category/add: Add a category
  • api/v1/book/add: Add a book
  • api/v1/books/{bookId}: Get a book by id
  • api/v1/books: Get a list of books
  • apiv1/books/expected-revenue:

4.1 Create entities class

To store Category, Author and Book to MySQL, we need create 3 entities

    @Data
    @Entity
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode(of = "id", callSuper = false)
    public class Author extends CommonEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
        private String name;
    }
    @Data
    @Entity
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode(of = "id", callSuper = false)
    public class Book extends CommonEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private Long categoryId;
        private Long authorId;
        private String name;
        private BigDecimal price;
        private LocalDate releaseDate;
        private LocalDateTime releaseTime;
    }
    @Data
    @Entity
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode(of = "id", callSuper = false)
    public class Category extends CommonEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
        private String name;
    }

4.2 Create repositories

We need create 3 repositories for 3 entities

    import com.tvd12.ezydata.database.EzyDatabaseRepository;
    import com.tvd12.ezydata.example.jpa.entity.Author;
    import com.tvd12.ezyfox.database.annotation.EzyRepository;
    @EzyRepository
    public interface AuthorRepository extends EzyDatabaseRepository {
    }
    import java.util.List;
    import com.tvd12.ezydata.database.EzyDatabaseRepository;
    import com.tvd12.ezydata.example.jpa.entity.Book;
    import com.tvd12.ezydata.example.jpa.result.SumBookPriceResult;
    import com.tvd12.ezyfox.database.annotation.EzyQuery;
    import com.tvd12.ezyfox.database.annotation.EzyRepository;
    import com.tvd12.ezyfox.util.Next;
    @EzyRepository
    public interface BookRepository extends EzyDatabaseRepository {
        Book findByNameAndAuthorId(String name, Long authorId);
        @EzyQuery("select e from Book e")
        List findBooks(Next next);
        @EzyQuery("select e from Book e where e.name < ?0 order by e.name")
        List findByNameLt(String name, Next next);
        @EzyQuery("select e from Book e where e.name > ?0 order by e.name")
        List findByNameGt(String name, Next next);
        @EzyQuery(value = "select sum(e.price) as sum from Book e", nativeQuery = true)
        SumBookPriceResult sumPrice();
    }
    import com.tvd12.ezydata.database.EzyDatabaseRepository;
    import com.tvd12.ezydata.example.jpa.entity.Category;
    import com.tvd12.ezyfox.database.annotation.EzyRepository;
    @EzyRepository
    public interface CategoryRepository extends EzyDatabaseRepository {
        Category findByName(String name);
    }

4.3 Save entities

Save a category, see more details

    final Category entity = dataToEntityConverter.toEntity(data);
    categoryRepository.save(entity);

Save an author, see more details

    final Author entity = dataToEntityConverter.toEntity(data);
    authorRepository.save(entity);

Save a book, see more details

    final Book book = dataToEntityConverter.toEntity(data);
    bookRepository.save(book);

4.4 Query data

Find a category by id, see more details

    Category category = categoryRepository.findById(request.getCategoryId());

Find an author by id, see more details

    Author author = authorRepository.findById(request.getAuthorId());

Find a book by name and author id, see more details

    Book existedBook = bookRepository.findByNameAndAuthorId(
        request.getBookName(),
        request.getAuthorId()
    );

Get sum of all book prices, see BookRepository and BookService to get more details

    @EzyQuery(value = "select sum(e.price) as sum from Book e", nativeQuery = true)
    SumBookPriceResult sumPrice();
    bookRepository.sumPrice().getSum()

Full source code available on Github

5. Conclusion

With EzyJPA you will work with database lot easier. With query string, you will don't need care about data and query result mapping, you will reduce a lot of your source code, save your time to focus to your business

Next

You can take a look the list of default functions.