Object.setXXX (Spring Data JPA Entity) генерирует исключение NullPointerException - PullRequest
0 голосов
/ 16 октября 2018

Я столкнулся с проблемой базовых объектов Spring Data JPA.Если объект существует и вызывает его метод установки, и если параметром может быть сущность, возвращаемая JpaRepository, он генерирует исключение NullPointerException.

Entity Cheat

@Entity
@Table(name = "cheat")
@DynamicInsert
@DynamicUpdate
@Getter
@Setter
@EqualsAndHashCode(exclude={"vote"})
@NoArgsConstructor
@RequiredArgsConstructor(staticName="of")
public class Cheat implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cheat_seq", length = 10)
    private Long cheatSeq;

    @Column(name = "question", unique = true, nullable = false)
    @NonNull
    private String question;

    @Column(name = "answer", unique = true, nullable = false)
    @NonNull
    private String answer;

    @Column(name = "writer_ip", nullable = false)
    @NonNull
    private String writerIP;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "reg_date", nullable = false)
    @NonNull
    private Date regDate;

    @Transient
    @NonNull
    private String regDateText;

    @OneToMany(mappedBy = "cheat", fetch=FetchType.EAGER)
    private Set<CheatVote> vote = new HashSet<CheatVote>();

    @Override
    public String toString() {
        return "Cheat [cheatSeq=" + cheatSeq + "]";
    }


}

И Entity CheatVote , представляющая собой коллекцию @ManyToOne из Cheat , ниже:

@Entity
@Table(name="cheat_vote")
@DynamicInsert
@DynamicUpdate
@Getter
@Setter
@RequiredArgsConstructor(staticName="of")
@NoArgsConstructor
public class CheatVote implements Serializable{

    private static final long serialVersionUID = 1L;

    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Id
    @Column(name="seq", nullable=false)
    private Long seq;

    @Column(name="val", nullable=false)
    @NonNull
    private Integer value;

    @Column(name="ip_address", nullable=false)
    @NonNull
    private String ipAddress;

    @JoinColumn(name="cheat_fk", referencedColumnName="cheat_seq")
    @ManyToOne(cascade=CascadeType.ALL)
    @NonNull
    private Cheat cheat;

    @Override
    public String toString() {
        return "CheatVote [seq=" + seq + "]";
    }


}

Уровень обслуживания находится ниже:

@Transactional
@Service
public class CheatVoteServiceImpl implements CheatVoteService{

    @Autowired
    private CheatVoteRepository repository;

    @Autowired
    private CheatService cheatService;

    @Override
    public void addGoodVote(Long cheatSeq, String ipAddress) throws NotFoundEntityException {
        Cheat cheat = cheatService.findOne(cheatSeq);

        CheatVote vote = new CheatVote();
        vote.setCheat(cheat);
        vote.setValue(CheatVoteRepository.VOTE_TYPE_GOOD);
        vote.setIpAddress(ipAddress);

        Set<CheatVote> votes = new HashSet<CheatVote>();
        votes.add(vote);
        cheat.setVote(votes);
        cheatService.addCheat(cheat);
        repository.save(vote);
    }
}

Уровень репозитория находится ниже:

public interface CheatVoteRepository extends JpaRepository<CheatVote, Long>{
    Integer VOTE_TYPE_GOOD = 1;

}

Код теста приведен ниже:

@Test
    public void voteTest() throws Exception{
        cheatService.addCheat(addDTO1);
        Cheat cheat = cheatService.findAll().get(0);
        assertEquals(0, cheat.getVote().size());

        cheatVoteService.addGoodVote(cheat.getCheatSeq(), "127.0.0.1");
    }

Два объекта DTO находятся ниже.Один из них:

@NoArgsConstructor
@Data
public class CheatAddNewDTO {

    private String ipAddress;
    private List<CheatUnit> unitList;
}

А другой:

@RequiredArgsConstructor(staticName="of")
@NoArgsConstructor
@Data
public class CheatUnit {

    @NotNull
    @NonNull
    @Mapping("question")
    private String question;

    @NotNull
    @NonNull
    @Mapping("answer")
    private String answer;

}

Выдает NullPointerException :

java.lang.NullPointerException: cheat
    at com.ddedderu.moonBladeQuiz.data.entity.CheatVote.setCheat(CheatVote.java:29)
    at com.ddedderu.moonBladeQuiz.data.service.CheatVoteServiceImpl.addGoodVote(CheatVoteServiceImpl.java:31)
    at com.ddedderu.moonBladeQuiz.data.service.CheatVoteServiceImpl$$FastClassBySpringCGLIB$$d089e475.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
    at com.ddedderu.moonBladeQuiz.data.service.CheatVoteServiceImpl$$EnhancerBySpringCGLIB$$b1f41534.addGoodVote(<generated>)
    at com.ddedderu.moonBladeQuiz.MoonBladeQuizApplicationTests.voteTest(MoonBladeQuizApplicationTests.java:85)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

После просмотра этой ошибкиСтеки, я подумал, что когда сущность задается в методе установки объекта, ее прокси-объект (может быть, используется с навыком AOP) делает что-то для работы с внутренней системой JPA.

Но почему я должен даже учитывать эту основную часть JPA?Или этот стек ошибок происходит из-за моей неправильной структуры сущностей?Что пошло не так?

И я сожалею, что не могу быстро отреагировать на ваш комментарий!

Не стесняйтесь запрашивать любой код, связанный с этим вопросом!

Спасибо.

1 Ответ

0 голосов
/ 16 октября 2018

NPE не исходит от JPA или Spring Data JPA.

Просто в этих трех строках:

    Cheat cheat = cheatService.findOne(cheatSeq);

    CheatVote vote = new CheatVote();
    vote.setCheat(cheat);

Чит не найден и поэтому равен null, а когда вы звоните vote.setCheat, Ломбок @NonNull аннотация вступает в силу и выдает исключение.

Чтобы устранить проблему, выполните одно из следующих действий:

  • убедитесь, что cheat не равно NULLперед настройкой.

  • удалить аннотацию @NonNull.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...