Spring Data findOne()NullPointerException [英] Spring Data findOne() NullPointerException

查看:104
本文介绍了Spring Data findOne()NullPointerException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我缺少一些核心概念,因为我遇到了几个问题,但让我们从这个问题开始:当具有 Subscription User 保留在数据库中时并且尝试使用 findOne(id)来获取它,我得到 NullPointerException .我尝试调试生成的代码的深处,并且由于某种原因,似乎调用了 Subscription 对象的 hashCode(),由于不清楚的原因,该对象也只有一个 id设置,所有其他属性均为 null ,但是因为它们(很可能)通过调用自己的 hashCode()参与了 hashCode()方法,我收到此异常.

因此,基本上我希望用户成为许多社区的一部分,在每个社区中,他都可以创建其内容的订阅.当我第一次调用 SubscriptionController 时,一切正常,并且创建了 User Subscription Community ,我可以看到他们在数据库中,一切都很好.但是然后当我在 UserSerivce 内部调用 CrudRepository UserRepository.findOne()时,我得到了例外.

我一直在努力解决这个问题,但没有任何运气,所以我真的希望有人可以花一些时间来帮助我.以下是课程:

用户:

  @Entity@数据@NoArgsConstructor公共类用户{@Column(nullable = false)@ID私有整数ID;@OneToMany(mappedBy =用户",fetch = FetchType.EAGER,级联= CascadeType.ALL)@JsonIgnore设置<订阅>订阅;@OneToMany(获取= FetchType.EAGER,级联= CascadeType.ALL)@JoinTable(joinColumns = {@JoinColumn(name ="user_id",referencedColumnName ="id")},inverseJoinColumns = {@JoinColumn(name ="payment_id",referencedColumnName ="id",唯一= true)})@JsonIgnore设置<付款>付款;public User(Integer userId){this.id = userId;}} 

订阅:

  @Entity@数据@NoArgsConstructor公共类订阅{@柱子@ID@GeneratedValue(策略= GenerationType.AUTO)@JsonIgnore私有整数ID;@ManyToOne(级联= {CascadeType.MERGE,CascadeType.REFRESH})@JoinColumn(name ="user_id",nullable = false)私人用户用户;@ManyToOne(级联= {CascadeType.MERGE,CascadeType.REFRESH})@JoinColumn(name ="community_id",nullable = false)私人社区社区;@Column(nullable = false)private Boolean isActive;@Column(nullable = false)私有Date endDate;@OneToMany(获取= FetchType.EAGER,级联= CascadeType.ALL)@加入表(joinColumns = {@JoinColumn(name ="subscription_id",referencedColumnName ="id")},inverseJoinColumns = {@JoinColumn(name ="payment_id",referencedColumnName ="id",唯一= true)})私人Set< Payment>付款;公共订阅(用户,社区社区,布尔值isActive){this.user =用户;this.community =社区;this.isActive = isActive;this.endDate = new Date();}} 

社区:

  @Data@实体@NoArgsConstructor公共类社区{@Column(nullable = false)@ID私有整数ID;@OneToMany(mappedBy ="community",提取= FetchType.LAZY,级联= {CascadeType.MERGE,CascadeType.REFRESH})@JsonIgnore私人Set< Subscription>订阅;公共社区(Integer communityId){this.id = communityId;}} 

我也为他们每个人提供服务:

UserService:

  @Service公共类UserService实现IService< User>.{@Autowired私有 UserRepository userRepository;@交易公共用户get(@NotNull整数userId){用户user = userRepository.findOne(userId);如果(用户==空)返回userRepository.save(new User(userId));返回用户;}@Override公共用户save(@有效用户){返回userRepository.save(user);}} 

SubscriptionService:

  @Service公共类SubscriptionService实现IService< Subscription>.{@AutowiredSubscriptionRepository subscriptionRepository;@AutowiredPaymentRepository付款库;@Override公共订阅get(@NotNull整数ID){返回subscriptionRepository.findOne(id);}公共订阅getByUserAndCommunity(@Valid用户用户,@ Valid社区社区){订阅subscription = subscriptionRepository.findByUserAndCommunity(用户,社区);如果(订阅!= null)返回订阅;subscription =新的Subscription(用户,社区,false);返回subscriptionRepository.save(subscription);}@交易公共订阅激活(@有效订阅订阅,@有效付款,@未来日期endDate){paymentRepository.save(payment);设置<付款>付款= subscription.getPayments();如果(付款==空)Payments = new HashSet<>();Payments.add(payment);subscription.setEndDate(endDate);subscription.setIsActive(true);返回subscriptionRepository.save(subscription);}@Override公共订阅save(@有效订阅e){返回subscriptionRepository.save(e);}} 

和CommunityService:

  @Service公共类CommunityService实现IService< Community>{@Autowired私有CommunityRepository社区存储库;@Override@交易公共社区获取(@NotNull 整数 id){社区社区= communityRepository.findOne(id);如果(社区== null)返回communityRepository.save(new Community(id));回归社区;}@Overridepublic Community save(@Valid Community community){返回communityRepository.save(community);}} 

控制器:

  @RestController公共类SubscriptionController {@Autowired私人SubscriptionService subscriptionService;@Autowired私有CommunityService communityService;@Autowired私人PaymentService PaymentService;@PostMapping("/subscribe")公共ResponseEntity< Subscription>subscription(@RequestParam("communityId")整数communityId,@ RequestBody @有效付款){if(!paymentService.checkPayment(付款))返回ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);VkAuthentication vkAuthentication =(VkAuthentication)SecurityContextHolder.getContext().getAuthentication();用户用户= vkAuthentication.getUser();社区社区= communityService.get(communityId);订阅subscription = subscriptionService.getByUserAndCommunity(user,community);日历calendar = Calendar.getInstance();日期newEndDate = DateUtils.addDays(新的Date(),calendar.getActualMaximum(Calendar.DAY_OF_MONTH));subscription = subscriptionService.activate(订阅,付款,newEndDate);返回ResponseEntity.status(HttpStatus.OK).body(subscription);}} 

这是一些堆栈跟踪:

  java.lang.NullPointerException:空在org.hibernate.engine.internal.StatefulPersistenceContext.getLoadedCollectionOwnerOrNull(StatefulPersistenceContext.java:786)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.event.spi.AbstractCollectionEvent.getLoadedOwnerOrNull(AbstractCollectionEvent.java:58)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在 org.hibernate.event.spi.InitializeCollectionEvent.(InitializeCollectionEvent.java:22) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1989)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.collection.internal.AbstractPersistentCollection $ 4.doWork(AbstractPersistentCollection.java:570)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:252)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:566)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:135)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:430)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在zhiyest.subscriptionsbackend.domain.User.hashCode(User.java:14)〜[classes/:na]在zhiyest.subscriptionsbackend.domain.Subscription.hashCode(Subscription.java:15)〜[classes/:na]在java.util.HashMap.hash(HashMap.java:338)〜[na:1.8.0_111]在java.util.HashMap.put(HashMap.java:611)〜[na:1.8.0_111]在 java.util.HashSet.add(HashSet.java:219) ~[na:1.8.0_111]在java.util.AbstractCollection.addAll(AbstractCollection.java:344)〜[na:1.8.0_111]在org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249)〜[hibernate-core-5.0.12.Final.jar:5.0.12.Final]在 ... 

我什至不知道为什么当 User findOne()时它为什么调用 Subscription.hashCode()./p>

更新:

org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke中的

 (SurroundingTransactionDetectorMethodInterceptor.java:57)〜[spring-data-commons-1.13.4.RELEASE.jar:na]...在zhiyest.subscriptionsbackend.logging.Logger.logAround(Logger.java:29)〜[classes/:na]...在zhiyest.subscriptionsbackend.services.UserService $$ EnhancerBySpringCGLIB $$ 6e00bac4.get(< generate>)〜[classes/:na]在zhiyest.subscriptionsbackend.security.VkAuthenticationProvider.authenticate(VkAuthenticationProvider.java:23)〜[classes/:na]在 zhiyest.subscriptionsbackend.security.VkAuthenticationProvider$$FastClassBySpringCGLIB$$24f3d662.invoke(<generated>) ~[classes/:na]...在zhiyest.subscriptionsbackend.security.VkAuthenticationProvider $$ EnhancerBySpringCGLIB $$ 4d8d8001.authenticate(< generate>)〜[classes/:na]在org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)〜[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]在org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)〜[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]在org.springframework.security.access.intercept.AbstractSecurityInterceptor.authenticateIfRequired(AbstractSecurityInterceptor.java:354)〜[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]在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 .

我希望它会有所帮助.

I think I'm missing some core concept, because I encounter several problems, but let's start with this one: when a User with a Subscription is persisted in database and I try to get it using findOne(id), I get NullPointerException. I tried to debug deep inside generated code and it appears that for some reason hashCode() of Subscription object is called, which also for unclear reason has only an id set and all other properties are null, but because they (probably) take part in the hashCode() method by calling their own hashCode(), I get this exception.

So basically what I want is user be a part of many communities, in each of them he can create a subscription to their content. When I first call to SubscriptionController, everything goes fine and it creates User, Subscription and Community, I can see them in database, all good. But then when I call UserRepository.findOne(), which is CrudRepository, inside UserSerivce - I get the exception.

I've been trying to figure this out for two weeks and no luck, so I really hope someone can spend some time helping me with this. Below are classes:

User:

@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;
    }
}

Subscription:

@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();
    }
}

Community:

@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;
    }
}

I also have services for each of them:

UserService:

@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);
    }
}

SubscriptionService:

@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);
    }
}

And CommunityService:

@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);
    }
}

Controller:

@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);
    }
}

And here's some stack trace:

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$4.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 ...

I don't even understand why does it call Subscription.hashCode() when it's findOne() for User...

upd:

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$$6e00bac4.get(<generated>) ~[classes/:na]
    at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider.authenticate(VkAuthenticationProvider.java:23) ~[classes/:na]
    at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider$$FastClassBySpringCGLIB$$24f3d662.invoke(<generated>) ~[classes/:na]
    ...
    at zhiyest.subscriptionsbackend.security.VkAuthenticationProvider$$EnhancerBySpringCGLIB$$4d8d8001.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]
    ...

解决方案

I guess that problem is @Data.

This lombok annotation is the cause of recursive dependencies (toString() and hashcode()). Try to use @Getter and @Setter instead of @Data.

I hope it will help.

这篇关于Spring Data findOne()NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆