当前位置: 首页 > 知识库问答 >
问题:

Lasy Fetch与Spring数据JPA

祁凯泽
2023-03-14

我创建一对一的关系,我希望有方法来获取相同的实体(Distributor.class),但是一个做懒惰的获取,另一个渴望。

@Entity
@Table
public class Distributor {

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

    private String name;
    private String site;

    @OneToOne(
            mappedBy = "distributor",
            cascade = CascadeType.ALL,
            orphanRemoval = true,
            fetch = FetchType.LAZY,
            optional = false
    )
    private Location location;

    public void setLocation(Location repositoryLocation) {
        if (repositoryLocation == null) {
            if (this.location != null) {
                this.location.setDataProvider(null);
            }
        }
        else {
            repositoryLocation.setDataProvider(this);
        }
        this.location = repositoryLocation;

    }

// getters/setters/constructor

    }

}
@Entity
@Table(name = "location")
public class Location {

    @Id
    private Long id;

    @Column(name = "country_code")
    private String countryCode;

    private Double longitude;

    private Double latitude;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    @JoinColumn(name = "id")
    private Distributor distributor;

    public Distributor getDistributor() {
        return distributor;
    }

    public void setDistributor(Distributor distributor) {
        this.distributor = distributor;
    }
// other getters/setters
}

我遇到的最大问题是,Spring数据JPA似乎忽略了FetchType,并急切地获取所有相关表(基于相关线程和Spring数据JPA文档)。使用分发服务器获取数据的所有Spring数据存储库方法。通过两个选项,从分发服务器和位置中急切地获取位置。通过使用@NamedEntityGraph:

@Entity
@Table
@NamedEntityGraph(
        name = "distributor-entity-graph",
        attributeNodes = {
                @NamedAttributeNode("location"),
        }
)
public class Distributor {
//spring data jpa methods
  @EntityGraph(value = "distributor-entity-graph", type = EntityGraph.EntityGraphType.LOAD)
    Optional<Distributor> findById(Long id);

如果使用这样的图,我会在位置上得到一个左外连接,虽然这是一种更好的急加载类型,但仍然是急加载。

到目前为止,我发现的一切似乎都是糟糕的解决办法。有没有什么更简洁的方法可以做到这一点,或者(首先在性能方面)只是不创建关系,而是按需获取位置?急于加载是一种气味,但当我获取单个分配器时,在大多数情况下我都想这样做,但在某些情况下我不想这样做,尤其是如果我获取findAll()。

共有1个答案

卢锋
2023-03-14

Hibernate会忽略每个双向一对一映射的父端上的LAZY,这些映射设置了mappdBy(或者使用JoinColVIII并且是可选的),因为它需要知道何时使用null或代理初始化字段。

你的问题是,即使你对孩子(Location)使用MapsId,家长仍然使用mappedBy

下面是如何实现延迟加载的双向关联(不过它也有缺点,请阅读到最后)。

家长

@Entity
public class TestParent {

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

  @OneToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "id")
  private TestChild child;
}
  • 孩子字段不是强制性的,它是有点hacky,你可以忽略它,并在需要时使用存储库获取孩子-你知道它的id
  • 因为这不是标准的父到子映射,所以您不能在字段上指定任何级联(这将反映您持久化它们的方式,所以一直读到最后),否则持久化将失败,因为它无法将id分配给子实体。
  • 可选=false是强制性的,否则无论如何都会被急切地获取。

小孩

public class TestChild {

  @Id
  private Long id;

  @OneToOne(fetch = FetchType.LAZY)
  @MapsId
  @JoinColumn(name = "id")
  private TestParent parent;
}

这就是你对孩子的定义,没有什么重要的改变。

坚持

EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();

TestParent parent = new TestParent();
TestChild child = new TestChild();
parent.setChild(child);
child.setParent(parent);

em.persist(parent);
em.persist(child);

em.getTransaction().commit();
em.close();

由于父实体不再级联到子实体,因此必须单独持久化子实体。

阅读更多。

 类似资料:
  • 问题是,Spring HATEOAS和Spring Data Rest之间有什么区别? 我觉得两者都可以做同样的事情,Spring数据Rest(作为Spring数据的一部分)似乎更有活力。 https://github.com/spring-projects/spring-hateoas https://github.com/spring-projects/spring-data-rest 你什么

  • 我无法解决这个问题。我得到了“线程中的异常”main”org.hibernate.LazyInitializationException:未能延迟初始化角色集合:org.sandy.domain.Location.items,没有会话或会话被关闭”我知道会话已关闭,但tx: notionation-drive@Transactional应该确保打开会话。它可以很好地与EAGER获取一起工作。哦,是

  • 我正在遵循入门指南[1],但是我已经从配置设置中删除了MySQL和analytics的内容,因为我不打算使用任何分析函数。但是,scdf服务后来崩溃了,因为没有配置数据源。 好的,所以似乎仍然需要在scdf-config-kafka.yml[2]中配置数据源(尽管从阅读文档来看,我认为它只用于分析内容)。 但为了什么?数据源用于持久化Kafka消息,还是在节点之间建立云流消息? 我找不到任何关于大

  • 我正在尝试迁移到Spring Data R2DBC,我找不到对Amazon Redshift数据库的支持,如果有支持,有人可以帮助我吗? 下面是spring文档url,它支持的数据库很少,但红移不在列表中。https://spring.io/projects/spring-data-r2dbc

  • spring-data-neo4j工件在获取资源时会导致向tinkerpop域发出拒绝访问警告。 我的pom.xml文件有以下相关依赖项: 运行maven时,我收到以下错误(仅提供前几行): 等等等等。 我尝试了几件运气不好的事情,例如: 将spring-data-neo4j pom中列出的3个tinkerpop项目的排除项添加到依赖项中 在我的任何pom文件或maven设置中都没有对任何repo

  • 我还没有找到在QueryDSL中声明这种SQL的任何方法。我能够编写两个select语句,但是我仍然无法将它们与结合起来。 最后,我想检索一个与给定查询匹配的ID列表。通常,相交的数量可以是20或30左右,这取决于我要搜索的键/值对的数量。 有没有人知道如何使用QueryDSL执行类似的操作?