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

标签 java spring hibernate spring-data-jpa spring-data

上下文

我将应用程序分为三层: 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/

相关文章:

java - 无法在 SQL 中更新给定字段

java - 从文本文件中读取大量数据的最快方法

java - 在java中根据年龄查找出生日期

java - 使用 MapSqlParameterSource 在 Spring MVC 中进行 Order by 子句查询

java - Hibernate如何以2位小数写Detachedcriteria?

java - Gridview 类似于 Java 中 hibernate 对象的显示?

java - 使用 group by 连接的 SQL 的 HQL 版本

java - 通过数据源配置属性与通过 hibernateProperties 配置属性

java - Spring MVC : What's the right way to register custom Validator in REST controller

java - 在 hibernate 统计中,加载和获取之间有什么区别