gpt4 book ai didi

java - 如何将手动 SQL 行映射与 CrudRepository (Spring Data) 混合

转载 作者:行者123 更新时间:2023-11-30 02:04:14 25 4
gpt4 key购买 nike

上下文

我将应用程序分为三层: Controller 、服务、存储库。这非常有用,因为我可以更改任何层上的内容而不影响其他层。

目前,我正在尝试优化一些查询,但有些地方实体图和生成的查询不足以满足我的需求。通过编写 native SQL 并使用现有的 @Entity 映射结果集,我相信我可以更快地生成数据。

问题

假设我有一些界面:

public interface UserRepository extends CrudRepository<User, Long> {}

如何扩展UserRepository以使用CrudRepository方法(例如save()findById() )同时还使用我自己的 native 查询方法。

我在带有 Spring Boot 的 Java 8 的每个租户数据库环境中使用 hibernate 作为我的持久性提供程序。我考虑过以下解决方案,但仍不满意:

  • JPQL - 在某些地方它非常有用并且可以节省大量样板文件。但对于复杂的查询或我想充分利用数据库规范化的地方,我发现它很难使用,并且宁愿拥有完全的控制权。
  • @Query 中的 NativeQuery - 需要在实体类中包含巨大的 @PostConstruct 注释。
  • Spring Data 查询语言 - 使用 @Entity 图时与上面类似(我发现其深度有限。)。

我在 Spring Data Docs 中找不到任何内容描述如何做到这一点,但我确信我已经在网络上的某个地方看到过这样的解决方案。

为了清楚起见,我希望做这样的事情:

public interface UserRepository extends CrudRepository<User, Long> {};

public class UserRepositoryImpl extends UserRepository {

public User doComplexQuery() {

List<Result> rows = query.("select * from ... ");
User user = new User(rows.get(0));
return user;

}

};

public class UserService {
@Autowired private UserRepository userRepository;
public User getUser() {
return userRepository.doComplexQuery();
}

public User saveUser(User user) {
return userRepository.save(user);
}
}

最佳答案

对我来说,最好和最简单的选择是您所描述的所有选项的组合, projections (如果我理解正确的话)。

我使用 Lombok 创建简单实体

@Data
@Builder
@NoArgConstructor
@AllArgsConstructor
@Entity
public class Model implements Serializable {
//...

private String name;

@OneToMany
private List<Subject> subjects;
}

@Data
@Builder
@NoArgConstructor
@AllArgsConstructor
@Entity
public class Subject implements Serializable {
//...
}

然后定义必要的投影,例如:

public interface ModelSubjects {
List<Subject> getSubjects();
}

public interface SomeProjection {
//...
}

然后根据需要扩展我的存储库:

public interface ModelRepo extends JpaRepository<Model, Long> {
@Query("select distinct m from Model m join fetch m.subjects where ...")
List<Model> getWithJPQLQuery(...);

@Query("select s as subjects from Model m join m.subjects s where ...")
List<ModelSubjects> getSubjectsWithJPQLQuery(...);

@Query(value = "some complex SQL query...", nativeQuery = true)
List<SomeProjection> getWithSQLQuery(...);

@EntityGraph(attributePaths = "subjects")
List<Model> findByName(String name);
}

已更新

复杂的例子(参见答案下的评论):

@Entity
public class Forest {
//...

private String name;

@OneToMany
private List<Tree> trees;
}

@Entity
public class Tree {
//...

@OneToMany
private List<Branch> branches;
}

@Entity
public class Branch {
//...
}
public interface BranchNumberByForest {
String getForestName();
Long getBranchNumber();
}

native 查询

public interface ForestRepo extends JpaRepository<Forest, Long> {
@Query(value = "" +
"select " +
" f.name as forestName, " +
" count(b.*) as branchNumber " +
"from " +
" forests f " +
" left join trees t on t.forest_id = f.id " +
" left join branches b on b.tree_id = t.id " +
"group by " +
" f.name", nativeQuery = true)
List<BranchNumberByForest> getBranchNumbers();
}

与JPQL相同

public interface ForestRepo extends JpaRepository<Forest, Long> {
@Query("" +
"select " +
" f.name as forestName, " +
" count(b) as branchNumber " +
"from " +
" Forest f " +
" left join f.trees t " +
" left join t.branches b " +
"group by " +
" f.name")
List<BranchNumberByForest> getBranchNumbers();
}

关于java - 如何将手动 SQL 行映射与 CrudRepository (Spring Data) 混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51829850/

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