gpt4 book ai didi

spring - 如何在查询数据库时为 JPA 实体中的列生成值?

转载 作者:行者123 更新时间:2023-12-02 07:23:07 25 4
gpt4 key购买 nike

我有一个如下所示的实体:

@Entity
@Table(uniqueConstraints={@UniqueConstraint(columnNames={"slug"})})
public class BlogPost {

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

@Column
private String title;

@Column
private String slug;
}

我想在坚持之前通过执行以下操作生成slug的值:

  • 标题从例如博客文章标题博客文章标题
  • 确保blog-post-title在BlogPost表中是唯一的,如果它不唯一,我想在标题上附加一些后缀,这样它就变成了例如blog-post-title-2

由于我需要在很多实体上执行此操作,因此我最初的想法是创建一个 EntityListener,它可以在 @PrePersist 处执行此操作。但是,文档通常指出我不应该调用 EntityManager 或 Query 方法,也不应该从生命周期回调访问任何其他实体对象。我需要这样做,以确保我生成的 slug 确实是唯一的。

我试图厚颜无耻,但无论如何,使用 Spring 将存储库自动连接到 EntityListener 中确实非常困难。

我应该如何最好地解决这个问题?

谢谢!

最佳答案

OndrejM 和 MirMasej 都绝对正确,生成 slug 不是在实体中完成的事情。我希望 EntityListeners 能够更“聪明”一点,但这不是一个选择。

我最终所做的是使用方面来完成我想要的事情。我不是“ Hook ”实体,而是 Hook CrudRepository 的 save 方法。

首先,我创建了一个注释,这样我就可以识别哪个字段需要被标记:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Slug {

/**
* The string slug is generated from
*/
String source() default "title";

/**
* Strategy for generating a slug
*/
Class strategy() default DefaultSlugGenerationStrategy.class;
}

然后,我创建了一个如下所示的方面:

@Aspect
@Component
public class SlugAspect {

... // Removed some code for bravity

@Before("execution(* org.springframework.data.repository.CrudRepository+.save(*))")
public void onRepoSave(JoinPoint joinPoint) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Object entity = joinPoint.getArgs()[0];

for (Field field: entity.getClass().getDeclaredFields()) {
Slug annotation = field.getAnnotation(Slug.class);

if (annotation != null) {
CrudRepository repository = (CrudRepository) joinPoint.getTarget();

Long count = 0L;
SlugGenerationStrategy generator = (SlugGenerationStrategy)annotation.strategy().newInstance();
String slug = generator.generateSlug(slugOrigin(entity));

if (id(entity) != null) {
Method method = repository.getClass().getMethod("countBySlugAndIdNot", String.class, Long.class);
count = (Long)method.invoke(repository, slug, id(entity));
} else {
Method method = repository.getClass().getMethod("countBySlug", String.class);
count = (Long)method.invoke(repository, slug);
}

// If count is zero, use the generated slug, or generate an incremented slug if count > 0 and then set it like so:
setSlug(entity, slug);
}
}
}
}

如果有人感兴趣的话,我将代码放在 github 上(尽管它仍然只是一个概念证明):https://github.com/cabrilo/jpa-slug

它依赖于 Spring Data 中的 CrudRepository 以及存储库上的这两个方法:countBySlug 和 countBySlugAndIdNot。

再次感谢您的回答。

关于spring - 如何在查询数据库时为 JPA 实体中的列生成值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32233089/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com