【发布时间】:2019-10-29 14:52:57
【问题描述】:
我有一个 spring 服务类,我正在通过 CRUD 加载一个 JPA 对象(目标)。这个目标类有一个设置为延迟加载的一对五映射。
我想在带有@Transactional 注释的spring 服务方法中查询该对象,并避免加载子对象。
当我执行以下代码时,所有子数据都被加载,惰性被忽略。
@Override
@Transactional
public boolean changeState(boolean enabled, final EventType eventType, final String deviceSerialNumber) {
final UniqueUser user = userService.getUser();
final Target target = targetRepository.findEventsByUserIdAndTenantIdAndTargetDeviceId(user.getUserId(), user.getTenantId(), deviceSerialNumber);
//here everything gets loaded
if (target == null) {
return false;
}
final List<EventHistory> events = target.getEvents().stream()
.filter(event -> event.getEventType() == eventType)
.filter(event -> event.isActive() != enabled)
.collect(Collectors.toList());
events.forEach(event -> event.setActive(enabled));
if (events.isEmpty()) {
return false;
}
return true;
}
映射:
@ToString
@Entity
@Table(name = "target")
public class Target {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
@Column(name = "id", unique = true)
private UUID id;
@Column(name = "user_id")
private String userId;
@Column(name = "tenant_id")
private String tenantId;
@Column(name = "target_device_id")
private String targetDeviceId;
@Column(name = "target_type")
private TargetType targetType;
@OneToMany(mappedBy = "target", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@JsonManagedReference
private List<EventHistory> events = new ArrayList<>();
public void addEvents(EventHistory event) {
events.add(event);
event.setTarget(this);
}
}
@Entity
@Data
@Table(name = "event_history")
public class EventHistory {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
@Column(name = "id", unique = true)
private UUID id;
@Column(name = "active")
private boolean active;
@OneToMany(mappedBy = "event", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private List<EventTimestamp> timestamps = new ArrayList<>();
@ManyToOne(optional = false, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "target_id", nullable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonBackReference
private Target target;
public void addTimestamps(EventTimestamp eventTimestamp) {
timestamps.add(eventTimestamp);
eventTimestamp.setEvent(this);
}
}
@Entity
@Data
@Table(name = "event_timestamp")
public class EventTimestamp {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
@Column(name = "id", unique = true)
private UUID id;
@Column(name = "due_timestamp")
private Timestamp dueTimestamp;
@Column(name = "period")
private String period;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "event_id", nullable = false)
@JsonBackReference
private EventHistory event;
所以我的问题是如何在事务注释函数中保持延迟加载?
【问题讨论】:
-
你能发布DAO代码吗?通常我认为没有必要将服务类注释为事务性的,尤其是当它只是调用始终是事务性的 DAO 时。
-
findById首先在持久性缓存中执行查找。只是,如果它找不到现有实例,它会访问数据库。你确定 Foo 之前没有加载吗?您能否验证此操作是否命中数据库? -
您在该服务方法中还做了什么?贴出完整代码
-
关键问题:您如何验证集合确实已加载?
-
我看到正在执行的sql
标签: java hibernate jpa spring-data-jpa spring-data