【发布时间】:2019-07-20 11:00:57
【问题描述】:
我正在获取一组对象,并尝试在 @ManyToOne 关系中使用 LAZY 加载来获取对象。但是,当我调用服务方法时,集合中的对象获取 NULL 值
List<Location> all = locationRepository.getLocations(ids);
Merchant merchant = all.get(0).getMerchant();
// merchant == null
LocationRepository.java
@Repository
public interface LocationRepository extends JpaRepository<Location, String> {
@Query(value = "SELECT * FROM b_location WHERE id IN :ids", nativeQuery = true)
List<Location> getLocations(@Param("ids") Set<String> ids);
}
Location.java
@Entity
@Table(name = "b_location")
public class Location {
@Id
@Column(name = "id")
private String id;
@Column(name = "merchant_id", nullable = false)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Long merchantId;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "merchant_id", referencedColumnName = "id", insertable = false, updatable = false)
private Merchant merchant;
@Column(name = "is_active")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private boolean isActive;
Merchant.java
@Entity
@Table(name = "b_merchant")
public class Merchant {
@Id
@Column(name = "id")
private Long id;
@Column(name = "merchant_name", nullable = false)
private String merchantName;
@Column(name ="is_premium", columnDefinition = "boolean default false", nullable = false)
private boolean isPremium;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@OneToMany(mappedBy = "merchant", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Location> shops;
我想做什么:
1) 调用另一个查询,例如:
@Query("SELECT l, l.merchant FROM Location l LEFT JOIN FETCH l.merchant WHERE l.id IN :ids")
List<Location> getLocations(@Param("ids") List<String> ids);
和
@Query("SELECT l FROM Location l LEFT JOIN FETCH l.merchant WHERE l.id IN :ids")
List<Location> getLocations(@Param("ids") List<String> ids);
和
@Query("from Location l left join fetch l.merchant where l.id IN (:ids)")
List<Location> getLocations(@Param("ids") List<String> ids);
2) 将 FetchType 更改为所有可能的类型 (fetch = FetchType.EAGER)
3) 使用
List<T> findAll(Iterable<ID> ids);
// and
List<Location> findByIdIn(List<String> ids);
附言
当我只得到一个对象时,它工作得非常好。例如:
Merchant merchant = locationRepository.findOne("11111").getMerchant();
更新
原来我对根本问题的理解是不正确的。在获取集合之前,我使用的是 locationRepository.save(location);手术。事实证明,JPA 有几个级别的缓存。我的问题是使用 EntityManager 解决缓存清理,例如:
entityManager.clear();
更多信息在这里: Invalidating JPA EntityManager session
但只要我的问题没有被正确提出,我建议 Maciej Kowalski 给出正确的答案。谢谢
【问题讨论】:
-
您应该将查询更改为“SELECT l FROM Location l ...”。您的 getLocations 方法返回位置实体列表
-
至于第二个选项,您必须在事务方法中进行。尝试在此方法中使用一些 Merchang getter -> locationRepository.findOne("11111").getMerchant().getId();
-
我认为是因为你的自定义查询或方法,但你为什么不使用
findAllByIdsdocs.spring.io/spring-data/jpa/docs/current/api/org/… -
@alex valuiskyi 谢谢。感谢您的帮助(“SELECT l FROM Location l ...”和@Transactional)。不幸的是它仍然不起作用
-
@Deadpool 我曾尝试使用您的评论 (List
findAll(Iterable ids);) 但它没有用。谢谢
标签: java hibernate spring-boot spring-data-jpa