为了使我的代码更清晰,我想引入一个通用存储库,每个存储库都可以扩展它,从而减少每个存储库中必须拥有的代码。问题是,不同类的 ID 不同。在一个(参见下面的示例)上它是
id
,在另一个上是 randomNumber
,在另一个上甚至可能是 @EmbeddedId。我想在存储库中有一个派生(或非派生)查询,通过 id 获取 One。
我想象有这样的事情:
public interface IUniversalRepository<T, K>{
@Query("select t from # {#entityName} where @id = ?1")
public T findById(K id);
}
id
)public interface IUniversalRepository<T, K>{
//should return the object with the id, reagardless of the column name
public T findById(K id);
}
// two example classes with different @Id fields
public class TaxRate {
@Id
@Column()
private Integer id;
...
}
public class Settings{
@Id
@Column() //cannot rename this column because it has to be named exactly as it is for backup reason
private String randomNumber;
...
}
// the Repository would be used like this
public interface TaxRateRepository extends IUniversalRepository<TaxRate, Integer> {
}
public interface SettingsRepository extends IUniversalRepository<TaxRate, String> {
}
很高兴收到建议。
通过“id 查询”检索 JPA 实体的想法并不像您想象的那么好,主要问题是速度要慢得多,特别是当您在事务中多次访问同一实体时:如果刷新模式设置为 AUTO (这实际上是合理的默认值)Hibernate 需要在执行 JPQL 查询之前执行脏检查并将更改刷新到数据库中,此外,Hibernate 不保证通过“id 查询”检索的实体实际上不是过时的 - 如果实体已经存在在持久化上下文中,Hibernate 基本上会忽略数据库数据。
通过 id 检索实体的最佳方法是调用
EntityManager#find(java.lang.Class<T>, java.lang.Object)
方法,该方法又会备份 CrudRepository#findById
方法,因此,您的 findByIdAndType(K id, String type)
实际上应该如下所示:
default Optional<T> findByIdAndType(K id, String type) {
return findById(id)
.filter(e -> Objects.equals(e.getType(), type));
}
但是,在 JQPL 查询中放置某种
id
占位符的愿望并没有那么糟糕 - 它的应用程序之一可以在分页查询中保持顺序稳定性。我建议您将相应的CR提交到spring-data
项目。