# jpa-best-practices **Repository Path**: kk70/jpa-best-practices ## Basic Information - **Project Name**: jpa-best-practices - **Description**: JPA Best Practices - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-08-30 - **Last Updated**: 2024-09-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Java 最佳实践:数据访问层、JPA、Ebean ## 前言 ## 技术栈 - Java 11 - [Lombok](https://projectlombok.org/) - [Ebean](https://ebean.io/) - [Liquibase](https://docs.liquibase.com/home.html) ## 为什么使用 `Ebean` ? - [支持所有主流数据库](https://ebean.io/docs/database/) - 支持 JPA 标准 - 支持级联修改数据 - 支持懒加载数据 - 支持 QueryDSL 查询 - 支持 View - 支持分库、分表 - 支持分页查询 - 支持二级缓存 - 支持数据软删除 - 支持数据审计 - 支持事务管理 - 使用 APT 技术在编译期 (compile-time) 增强实体、事务 - **没有反射**及**没有运行时生成字符码技术** ## 数据库表设计 ![drawSQL-db-schema.png](drawSQL-db-schema.png) - `employees` 职员信息表 - `departments` 部门信息表 - `salaries` 薪水记录表 ### 实体设计 **Employee.java** ```java /** * 员工. */ @Getter @Setter @Entity @Table(name = "employees") public class Employee { @Id @GeneratedValue private Integer id; @WhenCreated private Instant createTime; @WhenModified private Instant updateTime; private String name; private LocalDate birthday; @ManyToOne private Department department; } ``` **Department.java** ```java /** * 部门. */ @Getter @Setter @Entity @Table(name = "departments") public class Department { @Id @GeneratedValue private Integer id; private String name; @ManyToOne private Department parent; /** * 职员列表. */ @OneToMany(mappedBy = "department") private List employees; } ``` **Salary.java** ```java /** * 薪水. */ @Getter @Setter @Entity @Table(name = "salaries") public class Salary { @Id @GeneratedValue private Integer id; @WhenCreated private Instant createTime; private LocalDate payday; private BigDecimal salary; /** * 职员. */ @ManyToOne private Employee employee; } ``` lombok 与 Ebean 同时使用时应该避免在实体类中使用 lombok 的`@Data`注解(使用`@Getter` `@Setter`替代)。 被`@Entity`注解的类 Ebean 会自动生成 `toString` `hashCode` `equals` 函数。 ## 数据访问类 使用 EBean `@Transactional` 注解的堆栈 ```java java.lang.RuntimeException at cool.houge.demo.service.DemoService.transactionalAnnotation(DemoService.java:13) at cool.houge.demo.service.DemoServiceTest.transactionalAnnotation(DemoServiceTest.java:13) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:728) ```