Spring Data JPA 和 NamedEntityGraphs

2023-12-06

目前我正在努力只获取我需要的数据。 findAll() 方法需要根据调用位置来获取数据。 我不想最终为每个实体图编写不同的方法。 另外,我会避免调用实体管理器并自己形成(重复的)查询。 基本上我想使用 findAll 方法中的构建,但使用我喜欢的实体图。任何机会?

@Entity
@Table(name="complaints")
@NamedEntityGraphs({
    @NamedEntityGraph(name="allJoinsButMessages", attributeNodes = {
            @NamedAttributeNode("customer"),
            @NamedAttributeNode("handling_employee"),
            @NamedAttributeNode("genre")
    }),
    @NamedEntityGraph(name="allJoins", attributeNodes = {
            @NamedAttributeNode("customer"),
            @NamedAttributeNode("handling_employee"),
            @NamedAttributeNode("genre"),
            @NamedAttributeNode("complaintMessages")
    }),
    @NamedEntityGraph(name="noJoins", attributeNodes = {

    })
})
public class Complaint implements Serializable{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private long id;

    private Timestamp date;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customer")
    private User customer;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "handling_employee")
    private User handling_employee;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="genre")
    private Genre genre;

    private boolean closed;

    @OneToMany(mappedBy = "complaint", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<ComplaintMessage> complaintMessages = new ArrayList<ComplaintMessage>();

//getters and setters
}

还有我的 JPARepository

@Repository
public interface ComplaintRepository extends JpaRepository<Complaint, Long>{

    List<Complaint> findByClosed(boolean closed);

    @EntityGraph(value = "allJoinsButMessages" , type=EntityGraphType.FETCH)
    @Override
    List<Complaint> findAll(Sort sort);
}

我们遇到了类似的问题,并设计了几种前瞻性的解决方案,但对于似乎是一个常见问题,似乎没有一个优雅的解决方案。

1) 前缀。 Data jpa 为方法名称提供多个前缀(find、get...)。一种可能性是对不同的命名图使用不同的前缀。这是最少的工作,但向开发人员隐藏了该方法的含义,并且很有可能因加载错误的实体而导致一些不明显的问题。

@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
    @EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
    User findByUserID(int id);

    @EntityGraph(value = "User.membershipYears", type = EntityGraphType.LOAD)
    User readByUserId(int id);
}

2) 自定义存储库。另一种可能的解决方案是创建自定义查询方法并注入 EntityManager。该解决方案为您的存储库提供了最干净的接口,因为您可以将您的方法命名为有意义的名称,但是添加到代码中以提供解决方案会非常复杂,而且您需要手动获取实体管理器而不是使用 Spring 魔法。

interface UserRepositoryCustom {
    public User findUserWithMembershipYearsById(int id);
}

class UserRepositoryImpl implements UserRepositoryCustom {
    @PersistenceContext
    private EntityManager em;
    @Override
    public User findUserWithMembershipYearsById(int id) {
        User result = null;
        List<User> users = em.createQuery("SELECT u FROM users AS u WHERE u.id = :id", User.class)
                .setParameter("id", id)
                .setHint("javax.persistence.fetchgraph", em.getEntityGraph("User.membershipYears"))
                .getResultList();
        if(users.size() >= 0) {
            result = users.get(0);
        }
        return result;
    }
}

@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
    @EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
    User findByUserID(int id);
}

3)JPQL。本质上,这只是放弃命名实体图并使用 JPQL 来为您处理连接。我认为不理想。

@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
    @EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
    User findByUserID(int id);

    @Query("SELECT u FROM users WHERE u.id=:id JOIN??????????????????????????")
    User findUserWithTags(@Param("id") final int id);
}

我们选择了选项 1,因为它是最简单的实现方式,但这确实意味着当我们使用存储库时,我们必须查看 fetch 方法,以确保我们使用的是具有正确实体图的方法。祝你好运。

Sources:

  • 使用 Spring 具有不同视图的 JPA EntityGraph
  • https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods

我没有足够的声誉来发布我的所有来源。对不起 :(

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Data JPA 和 NamedEntityGraphs 的相关文章

随机推荐

  • 如何使用扫描仪测试 JUnit 方法?

    我有一个类 它读取文件并使用扫描仪接收用户输入 如果扫描仪等于该文件中一行的一部分 它将显示同一行中的字符串 我该如何为此创建一个 Junit 测试方法 这是我想要测试方法的一些代码 Scanner Input new Scanner Sy
  • 获取 TensorFlow 训练的模型中某些权重的值

    我已经用 TensorFlow 训练了一个 ConvNet 模型 我想在层中获得特定的权重 例如在 torch7 中我只需访问model modules 2 weights 获取第 2 层的权重 我如何在 TensorFlow 中做同样的事
  • 空格键不适用于仅适用于 Flutter Web Production 构建的 TextField

    每当我尝试按 Space 里面一个文本域Flutter Web 版本 生产 的它不执行任何操作 但是 该行为不会在 flutter web 调试环境中复制 到目前为止我发现了什么 Flutter Web 仅受 Chrome 浏览器支持 但截
  • HTML 内容适合 UIWebview,无需缩小

    我正在利用UIWebView渲染一些 HTML 然而 虽然我的 webview 的宽度是 320 但我的 HTML 仍然显示全宽并且可以水平滚动 我想要实现与本机邮件应用程序实现的相同的目标 即它适合该宽度内的所有内容而不缩小 本机邮件应用
  • Phalcon:控制器和模型中2个函数“initialize”和“onConstruct”的顺序

    我检查了一下 发现Controller上的执行顺序是 onConstruct 然后 initialize 而Model上的执行顺序是 initialize 然后 onConstruct 那么为什么这些方法在Controller和Model上
  • R 绘图:除 pdf 之外的设备的字符损坏/丢失

    我遇到一个问题 某些图形设备打印丢失的字形框而不是字符 实际上 到目前为止我尝试过的唯一可以渲染字符的设备是 PDF 由于我最近更新了 R 并重建了一堆软件包 我怀疑这可能与它有关 这是比较四个设备的输出的屏幕截图 jpeg pdf svg
  • 如何拆分列表并将它们作为单独的参数传递?

    给出定义 def egg2 arg1 arg2 print arg1 print arg2 argList egg1 egg2 我怎样才能简单地打电话egg2使用列表 我想要相同的效果egg2 argList 0 argList 1 但不必
  • 如何将工作簿中的工作表复制到另一个工作簿

    我有这段代码可以将 VBA Access 中的工作簿中的工作表复制到另一个工作簿 文件 Dim File1 as String Dim File2 as String File1 D File1 xls File2 D File2 xls
  • Android Things 的内部版本号/指纹

    我正在使用开发者预览版 of 安卓事物 on my 树莓派3现在 预览2发布后 我问自己我的 RPi 是否可以通过 OTA 获得它 在哪里可以找到内部版本号来检查我的设备 generic iot rpi3 rpi3 7 0 NIF73 35
  • Selenium 和 Google - 如何使用 cookie?

    我目前正在 AdWords 上使用 Selenium 构建一个报告工具 不 我不能使用 Google 的 API 因为它不提供我想要的功能 我试图避免登录和注销 因为我知道频繁登录和注销并不像基于 cookie 的身份验证那么方便 我有以下
  • 如何向标签添加选取框

    我的 UIView 顶部有一个标签 我在计时器的帮助下通过数组在其上显示一些消息 但现在我希望这些消息以 MARQUEE 样式显示 我没有任何方式启动 任何源代码 使用方法 任何动画风格 任何不同的方法 提前致谢 这是一个想法 在 UILa
  • 更改命令提示符文本大小 C++

    我用 C 开发了一个只能在 Windows 上运行的控制台应用程序 我想在程序运行时更改命令提示符的文本大小 我做了一些搜索 但是找不到任何可以解决问题的东西 每个人都在谈论改变颜色 无论如何 如果可能的话 我如何更改命令提示符的文本大小
  • BCrypt::Errors::InvalidSalt:无效盐设计

    当我尝试创建新用户时出现此错误 如下所示 gt gt User create email gt email protected password gt hello BCrypt Errors InvalidSalt invalid salt
  • DigitalOcean 上的 NodeJS 服务器使用 socket.io 返回连接被拒绝

    我试图将 socket io 引入到我用 Laravel 和 AngularJS 开发的应用程序中 该应用程序在我的计算机上运行良好 但是当我尝试使其在服务器上运行时 我收到错误 GET 净 ERR CONNECTION REFUSED 服
  • Git hook 检查标签名称

    是否有任何 git hook 可以检查新 git 标签的名称或字符串 甚至可能在 提交 新标签之前 例如类似预提交的东西 但针对标签 我的问题的目的是我想禁止 abc 或 v1 2 3 格式的git标签名称 Git 标签名称应始终严格遵循
  • 为 Android 创建的新 Facebook 应用程序发布权限不起作用。使用 Facebook sdk 3.14.xx 和示例

    我正在使用 facebook sdk 3 14 最新更新的 sdk 并为 android 平台创建应用程序 就像其他旧应用程序一样 我添加了相同的选项和所有内容 我想使用共享照片功能 因为我使用下面的代码来添加publish actions
  • Websocket 已断开 连接呼叫失败

    我正在关注 Django Channel 2 教程 我遵循了所有步骤 但控制台连接失败 我注意到当我将 Channel layer 添加到设置时会出现此问题 当我删除 Channel layer 时连接会成功 我该如何解决这个问题 Mana
  • Maven Surefire下运行测试时找不到JSTL标签库

    我有一个基于 Servlet 的应用程序 OAuth 实现 它将一些响应呈现委托给 JSP 如下例所示 private void doLoginPage AuthorizationSession authzSession String er
  • 授权后在 Google+ Stream 上分享

    我一直在尝试通过我的应用程序在用户墙上发布内容 就连我也已经厌倦了 facebook Linkedin Twitter 我所做的是从这些应用程序正确授权后 我终于保存了它的令牌 如果他们在我的申请上张贴 我就会将其张贴在他们的墙上 现在继续
  • Spring Data JPA 和 NamedEntityGraphs

    目前我正在努力只获取我需要的数据 findAll 方法需要根据调用位置来获取数据 我不想最终为每个实体图编写不同的方法 另外 我会避免调用实体管理器并自己形成 重复的 查询 基本上我想使用 findAll 方法中的构建 但使用我喜欢的实体图