本教程不是关于Hibernate或Spring Boot如何入门,相反,我们将研究一起使用它们时可能遇到的一些常见错误以及如何解决它们。
我们将使用:
Spring Data Envers允许我们访问由Hibernate Envers管理的实体修订版。Jackson Annotations还将帮助我们避免由JPA关系引起的常见Stack Overflow错误。
Jackson DataType Hibernate Module将有助于Hibernate类型和延迟加载方面。
我们将使用H2来运行我们的项目。
在这个例子中,我们将使用JPA来创建大学和学生。将通用逻辑和属性存储在超类中总是一个好主意。
我们将为实体创建一个超类,并在其中存储公共属性。我们来看看我们的 BaseEntity 班级
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE) @MappedSuperclass @EntityListeners({AuditingEntityListener.class}) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public abstract class BaseEntity { @Id @GeneratedValue Long id; @CreatedDate LocalDateTime createdAt; @LastModifiedDate LocalDateTime updatedAt; }
你可以注意到的一件事是我没有在这个类使用Lombok 的@Data。@Data注释会自动添加@ToString注释,这可能会导致Stack Overflow错误。因此,最好手动管理注释。
@MappedSuperclass注释允许实体从基类继承属性。如果要从基类继承属性,则此批注非常重要。
@EntityListeners({AuditingEntityListener.class})启用审计。我们正在使用@CreatedDate 和 @LastModifiedDate捕获创建或修改实体的时间。这将由Spring Data JPA处理。
@JsonIdentityInfo将我们的实体转换为JSON时,将避免Stack Overflow错误。由于我们的实体之间的双向关系,这个注释是打破无限循环所必需的。
根据你的需求查看@JsonBackReference 并 @JsonManagedReference它们是否更符合您的要求。
我们来看看我们的大学和学生实体:
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder @FieldDefaults(level = AccessLevel.PRIVATE) @Entity @Audited public class Student extends BaseEntity{ String name; @ManyToOne University university; }
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder @FieldDefaults(level = AccessLevel.PRIVATE) @Entity @Audited public class University extends BaseEntity{ String name; String city; @OneToMany(mappedBy = "university") Set<Student> students = new HashSet<>(); }
@Audited 管理实体上的审计(跟踪更改)
配置
检查运行项目所需的配置。
Hibernate杰克逊模块
@Bean public Module hibernateModule(){ return new Hibernate5Module(); }
我们正在注册一个新的Jackson模块。Spring Boot会自动检测它并将其注册到ObjectMapperbean。
Hibernate Envers
要启用Envers审核,我们必须扩展我们的存储库RevisionRepository。
看看UniversityRepository:
public interface UniversityRepository extends RevisionRepository<University, Long, Long>, JpaRepository<University,Long> { }
StudentRepository:
public interface StudentRepository extends RevisionRepository<Student, Long, Long>, JpaRepository<Student,Long> { }
我们还必须用@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)注释我们的主类。
Spring Data Auditing
为了实现这一点,我们必须用@EnableJpaAuditing注释我们的主类。
我们来看看吧。
@SpringBootApplication @EnableJpaAuditing @EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class) public class HibernateTipsApplication { public static void main(String[] args) { SpringApplication.run(HibernateTipsApplication.class, args); } }
可以在 GitHub上 找到完整的例子 。点击标题看原文!