Spring 数据 findOne() NullPointerException
Spring Data findOne() NullPointerException
我想我遗漏了一些核心概念,因为我遇到了几个问题,但让我们从这个问题开始:当 User
和 Subscription
在数据库中持久化时,我尝试使用 findOne(id)
获取它,我得到 NullPointerException
。我试图深入调试生成的代码,似乎由于某种原因调用了 Subscription
对象的 hashCode()
,由于不明确的原因,它只有一个 id
集,所有其他属性都是 null
,但是因为他们(可能)通过调用他们自己的 hashCode()
参与了 hashCode()
方法,我得到了这个异常。
所以基本上我想要的是用户成为许多社区的一部分,在每个社区中他都可以创建对其内容的订阅。当我第一次调用 SubscriptionController
时,一切正常,它创建了 User
、Subscription
和 Community
,我可以在数据库中看到它们,一切正常。但是当我在 UserSerivce
中调用 UserRepository.findOne()
,即 CrudRepository
时 - 我得到了异常。
我已经尝试解决这个问题两个星期了,但没有成功,所以我真的希望有人能花一些时间帮助我解决这个问题。 下面是类:
用户:
@Entity
@Data
@NoArgsConstructor
public class User {
@Column(nullable = false)
@Id
private Integer id;
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JsonIgnore
Set<Subscription> subscriptions;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "payment_id", referencedColumnName = "id", unique = true)}
)
@JsonIgnore
Set<Payment> payments;
public User(Integer userId) {
this.id = userId;
}
}
订阅:
@Entity
@Data
@NoArgsConstructor
public class Subscription {
@Column
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@JsonIgnore
private Integer id;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name = "user_id", nullable = false)
private User user;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name = "community_id", nullable = false)
private Community community;
@Column(nullable = false)
private Boolean isActive;
@Column(nullable = false)
private Date endDate;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
joinColumns = {@JoinColumn(name = "subscription_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "payment_id", referencedColumnName = "id", unique = true)}
)
private Set<Payment> payments;
public Subscription(User user, Community community, Boolean isActive) {
this.user = user;
this.community = community;
this.isActive = isActive;
this.endDate = new Date();
}
}
社区:
@Data
@Entity
@NoArgsConstructor
public class Community {
@Column(nullable = false)
@Id
private Integer id;
@OneToMany(mappedBy = "community", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JsonIgnore
private Set<Subscription> subscriptions;
public Community(Integer communityId) {
this.id = communityId;
}
}
我也为他们每个人提供服务:
用户服务:
@Service
public class UserService implements IService<User> {
@Autowired
private UserRepository userRepository;
@Transactional
public User get(@NotNull Integer userId) {
User user = userRepository.findOne(userId);
if (user == null)
return userRepository.save(new User(userId));
return user;
}
@Override
public User save(@Valid User user) {
return userRepository.save(user);
}
}
订阅服务:
@Service
public class SubscriptionService implements IService<Subscription> {
@Autowired
SubscriptionRepository subscriptionRepository;
@Autowired
PaymentRepository paymentRepository;
@Override
public Subscription get(@NotNull Integer id) {
return subscriptionRepository.findOne(id);
}
public Subscription getByUserAndCommunity(@Valid User user, @Valid Community community) {
Subscription subscription = subscriptionRepository.findByUserAndCommunity(user, community);
if (subscription != null)
return subscription;
subscription = new Subscription(user, community, false);
return subscriptionRepository.save(subscription);
}
@Transactional
public Subscription activate(@Valid Subscription subscription, @Valid Payment payment, @Future Date endDate) {
paymentRepository.save(payment);
Set<Payment> payments = subscription.getPayments();
if (payments == null)
payments = new HashSet<>();
payments.add(payment);
subscription.setEndDate(endDate);
subscription.setIsActive(true);
return subscriptionRepository.save(subscription);
}
@Override
public Subscription save(@Valid Subscription e) {
return subscriptionRepository.save(e);
}
}
和社区服务:
@Service
public class CommunityService implements IService<Community> {
@Autowired
private CommunityRepository communityRepository;
@Override
@Transactional
public Community get(@NotNull Integer id) {
Community community = communityRepository.findOne(id);
if (community == null)
return communityRepository.save(new Community(id));
return community;
}
@Override
public Community save(@Valid Community community) {
return communityRepository.save(community);
}
}
控制器:
@RestController
public class SubscriptionController {
@Autowired
private SubscriptionService subscriptionService;
@Autowired
private CommunityService communityService;
@Autowired
private PaymentService paymentService;
@PostMapping("/subscribe")
public ResponseEntity<Subscription> subscribe(@RequestParam("communityId") Integer communityId, @RequestBody @Valid Payment payment) {
if(!paymentService.checkPayment(payment))
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(null);
VkAuthentication vkAuthentication = (VkAuthentication) SecurityContextHolder.getContext().getAuthentication();
User user = vkAuthentication.getUser();
Community community = communityService.get(communityId);
Subscription subscription = subscriptionService.getByUserAndCommunity(user, community);
Calendar calendar = Calendar.getInstance();
Date newEndDate = DateUtils.addDays(new Date(), calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
subscription = subscriptionService.activate(subscription, payment, newEndDate);
return ResponseEntity
.status(HttpStatus.OK)
.body(subscription);
}
}
这是一些堆栈跟踪:
java.lang.NullPointerException: null
at org.hibernate.engine.internal.StatefulPersistenceContext.getLoadedCollectionOwnerOrNull(StatefulPersistenceContext.java:786) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.event.spi.AbstractCollectionEvent.getLoadedOwnerOrNull(AbstractCollectionEvent.java:58) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.event.spi.InitializeCollectionEvent.<init>(InitializeCollectionEvent.java:22) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1989) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.doWork(AbstractPersistentCollection.java:570) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:252) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:566) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:135) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:430) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at zhiyest.subscriptionsbackend.domain.User.hashCode(User.java:14) ~[classes/:na]
at zhiyest.subscriptionsbackend.domain.Subscription.hashCode(Subscription.java:15) ~[classes/:na]
at java.util.HashMap.hash(HashMap.java:338) ~[na:1.8.0_111]
at java.util.HashMap.put(HashMap.java:611) ~[na:1.8.0_111]
at java.util.HashSet.add(HashSet.java:219) ~[na:1.8.0_111]
at java.util.AbstractCollection.addAll(AbstractCollection.java:344) ~[na:1.8.0_111]
at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at ...
我什至不明白为什么 User
的 findOne()
会调用 Subscription.hashCode()
...
更新:
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) ~[spring-data-commons-1.13.4.RELEASE.jar:na]
...
at zhiyest.subscriptionsbackend.logging.Logger.logAround(Logger.java:29) ~[classes/:na]
...
at zhiyest.subscriptionsbackend.services.UserService$$EnhancerBySpringCGLIB$e00bac4.get(<generated>) ~[classes/:na]
at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider.authenticate(VkAuthenticationProvider.java:23) ~[classes/:na]
at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider$$FastClassBySpringCGLIB$f3d662.invoke(<generated>) ~[classes/:na]
...
at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider$$EnhancerBySpringCGLIB$d8d8001.authenticate(<generated>) ~[classes/:na]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.authenticateIfRequired(AbstractSecurityInterceptor.java:354) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:229) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
...
我猜这个问题是 @Data
。
这个 lombok 注释是递归依赖的原因(toString()
和 hashcode()
)。
尝试使用 @Getter
和 @Setter
而不是 @Data
.
希望对您有所帮助。
这似乎是特定版本的 Hibernate 中的错误(请参阅下面第一个 post)。如果您有一组嵌套的其他 Hibernate 实体,在其 hashCode() 方法中访问它们似乎有问题。我通过调试确认了这一点。
您可以手动生成一个 hash/code 等号并删除另一个实体。或者你可以在你的 Lombok 中做这样的事情,下面第二个 post 中的评论建议:
@EqualsAndHashCode(exclude={"subscriptions"})
我说“某事”是因为我没有仔细阅读你的对象图,看不出你应该排除哪一个。但这是一个简单的解决方案,通常,将对象的附属内容作为其逻辑标识的一部分是没有意义的。
Hibernate 4.2.20 Object HashCode Method Causing NullPointerException
How do you retrieve nested Sets?
我想我遗漏了一些核心概念,因为我遇到了几个问题,但让我们从这个问题开始:当 User
和 Subscription
在数据库中持久化时,我尝试使用 findOne(id)
获取它,我得到 NullPointerException
。我试图深入调试生成的代码,似乎由于某种原因调用了 Subscription
对象的 hashCode()
,由于不明确的原因,它只有一个 id
集,所有其他属性都是 null
,但是因为他们(可能)通过调用他们自己的 hashCode()
参与了 hashCode()
方法,我得到了这个异常。
所以基本上我想要的是用户成为许多社区的一部分,在每个社区中他都可以创建对其内容的订阅。当我第一次调用 SubscriptionController
时,一切正常,它创建了 User
、Subscription
和 Community
,我可以在数据库中看到它们,一切正常。但是当我在 UserSerivce
中调用 UserRepository.findOne()
,即 CrudRepository
时 - 我得到了异常。
我已经尝试解决这个问题两个星期了,但没有成功,所以我真的希望有人能花一些时间帮助我解决这个问题。 下面是类:
用户:
@Entity
@Data
@NoArgsConstructor
public class User {
@Column(nullable = false)
@Id
private Integer id;
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JsonIgnore
Set<Subscription> subscriptions;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "payment_id", referencedColumnName = "id", unique = true)}
)
@JsonIgnore
Set<Payment> payments;
public User(Integer userId) {
this.id = userId;
}
}
订阅:
@Entity
@Data
@NoArgsConstructor
public class Subscription {
@Column
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@JsonIgnore
private Integer id;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name = "user_id", nullable = false)
private User user;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name = "community_id", nullable = false)
private Community community;
@Column(nullable = false)
private Boolean isActive;
@Column(nullable = false)
private Date endDate;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
joinColumns = {@JoinColumn(name = "subscription_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "payment_id", referencedColumnName = "id", unique = true)}
)
private Set<Payment> payments;
public Subscription(User user, Community community, Boolean isActive) {
this.user = user;
this.community = community;
this.isActive = isActive;
this.endDate = new Date();
}
}
社区:
@Data
@Entity
@NoArgsConstructor
public class Community {
@Column(nullable = false)
@Id
private Integer id;
@OneToMany(mappedBy = "community", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JsonIgnore
private Set<Subscription> subscriptions;
public Community(Integer communityId) {
this.id = communityId;
}
}
我也为他们每个人提供服务:
用户服务:
@Service
public class UserService implements IService<User> {
@Autowired
private UserRepository userRepository;
@Transactional
public User get(@NotNull Integer userId) {
User user = userRepository.findOne(userId);
if (user == null)
return userRepository.save(new User(userId));
return user;
}
@Override
public User save(@Valid User user) {
return userRepository.save(user);
}
}
订阅服务:
@Service
public class SubscriptionService implements IService<Subscription> {
@Autowired
SubscriptionRepository subscriptionRepository;
@Autowired
PaymentRepository paymentRepository;
@Override
public Subscription get(@NotNull Integer id) {
return subscriptionRepository.findOne(id);
}
public Subscription getByUserAndCommunity(@Valid User user, @Valid Community community) {
Subscription subscription = subscriptionRepository.findByUserAndCommunity(user, community);
if (subscription != null)
return subscription;
subscription = new Subscription(user, community, false);
return subscriptionRepository.save(subscription);
}
@Transactional
public Subscription activate(@Valid Subscription subscription, @Valid Payment payment, @Future Date endDate) {
paymentRepository.save(payment);
Set<Payment> payments = subscription.getPayments();
if (payments == null)
payments = new HashSet<>();
payments.add(payment);
subscription.setEndDate(endDate);
subscription.setIsActive(true);
return subscriptionRepository.save(subscription);
}
@Override
public Subscription save(@Valid Subscription e) {
return subscriptionRepository.save(e);
}
}
和社区服务:
@Service
public class CommunityService implements IService<Community> {
@Autowired
private CommunityRepository communityRepository;
@Override
@Transactional
public Community get(@NotNull Integer id) {
Community community = communityRepository.findOne(id);
if (community == null)
return communityRepository.save(new Community(id));
return community;
}
@Override
public Community save(@Valid Community community) {
return communityRepository.save(community);
}
}
控制器:
@RestController
public class SubscriptionController {
@Autowired
private SubscriptionService subscriptionService;
@Autowired
private CommunityService communityService;
@Autowired
private PaymentService paymentService;
@PostMapping("/subscribe")
public ResponseEntity<Subscription> subscribe(@RequestParam("communityId") Integer communityId, @RequestBody @Valid Payment payment) {
if(!paymentService.checkPayment(payment))
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(null);
VkAuthentication vkAuthentication = (VkAuthentication) SecurityContextHolder.getContext().getAuthentication();
User user = vkAuthentication.getUser();
Community community = communityService.get(communityId);
Subscription subscription = subscriptionService.getByUserAndCommunity(user, community);
Calendar calendar = Calendar.getInstance();
Date newEndDate = DateUtils.addDays(new Date(), calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
subscription = subscriptionService.activate(subscription, payment, newEndDate);
return ResponseEntity
.status(HttpStatus.OK)
.body(subscription);
}
}
这是一些堆栈跟踪:
java.lang.NullPointerException: null
at org.hibernate.engine.internal.StatefulPersistenceContext.getLoadedCollectionOwnerOrNull(StatefulPersistenceContext.java:786) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.event.spi.AbstractCollectionEvent.getLoadedOwnerOrNull(AbstractCollectionEvent.java:58) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.event.spi.InitializeCollectionEvent.<init>(InitializeCollectionEvent.java:22) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1989) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.doWork(AbstractPersistentCollection.java:570) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:252) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:566) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:135) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:430) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at zhiyest.subscriptionsbackend.domain.User.hashCode(User.java:14) ~[classes/:na]
at zhiyest.subscriptionsbackend.domain.Subscription.hashCode(Subscription.java:15) ~[classes/:na]
at java.util.HashMap.hash(HashMap.java:338) ~[na:1.8.0_111]
at java.util.HashMap.put(HashMap.java:611) ~[na:1.8.0_111]
at java.util.HashSet.add(HashSet.java:219) ~[na:1.8.0_111]
at java.util.AbstractCollection.addAll(AbstractCollection.java:344) ~[na:1.8.0_111]
at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at ...
我什至不明白为什么 User
的 findOne()
会调用 Subscription.hashCode()
...
更新:
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) ~[spring-data-commons-1.13.4.RELEASE.jar:na]
...
at zhiyest.subscriptionsbackend.logging.Logger.logAround(Logger.java:29) ~[classes/:na]
...
at zhiyest.subscriptionsbackend.services.UserService$$EnhancerBySpringCGLIB$e00bac4.get(<generated>) ~[classes/:na]
at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider.authenticate(VkAuthenticationProvider.java:23) ~[classes/:na]
at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider$$FastClassBySpringCGLIB$f3d662.invoke(<generated>) ~[classes/:na]
...
at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider$$EnhancerBySpringCGLIB$d8d8001.authenticate(<generated>) ~[classes/:na]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.authenticateIfRequired(AbstractSecurityInterceptor.java:354) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:229) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
...
我猜这个问题是 @Data
。
这个 lombok 注释是递归依赖的原因(toString()
和 hashcode()
)。
尝试使用 @Getter
和 @Setter
而不是 @Data
.
希望对您有所帮助。
这似乎是特定版本的 Hibernate 中的错误(请参阅下面第一个 post)。如果您有一组嵌套的其他 Hibernate 实体,在其 hashCode() 方法中访问它们似乎有问题。我通过调试确认了这一点。
您可以手动生成一个 hash/code 等号并删除另一个实体。或者你可以在你的 Lombok 中做这样的事情,下面第二个 post 中的评论建议:
@EqualsAndHashCode(exclude={"subscriptions"})
我说“某事”是因为我没有仔细阅读你的对象图,看不出你应该排除哪一个。但这是一个简单的解决方案,通常,将对象的附属内容作为其逻辑标识的一部分是没有意义的。
Hibernate 4.2.20 Object HashCode Method Causing NullPointerException
How do you retrieve nested Sets?