Почему объект сущности будет отсоединен после того, как метод вернет его? (Весенние данные JPA) - PullRequest
0 голосов
/ 21 февраля 2020

Решено: Проблема была в аспекте округления, который каким-то образом изменял возвращаемое значение в прокси. Извините за неопровержимый вопрос. Может, кто-то узнает мою вину. И спасибо за полезные ответы!

У меня проблема с консольным приложением весенней загрузки. Я использую также весенние данные JPA для сохранения. Все работает хорошо, я могу сохранить и найти объекты, но когда метод класса обслуживания возвращает объект, он будет отсоединен. Когда я хочу использовать возвращенный объект, приложение перестает работать, потому что значение объекта равно нулю.

Это просто пример точки.

@Entity
@Table(name = "person")
public class Person {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    private int id;
    private String name;
    @Convert(converter = LocalDateAttributeConverter.class)
    private LocalDate birth;

    public Person() {
    }
    //getter, setter..
}
public interface PersonRepository extends CrudRepository<Person, Long> {

    public Person findByName(String name);

}
public class Service {

    @Autowired
    private PersonRepository personRepository;

    public Person findPersonByName(String name) {
        return personRepository.findByName(name); // System.out.println(person.name) -> someone
    }
}
public class App {

    private Service service;

    public void doSomething(){
        Person person = service.findPersonByName("someone"); 
        // System.out.println(person.name) -> nullpointerEx
    }
} 
//The player like person in the exaple. I must cover some detail in the package names. 
//This is the real exception. As a say above, the code it's just a raw example. Probably don't match for this.
Hibernate: select player0_.id as id1_7_, player0_1_.email as email2_7_, player0_1_.password as password3_7_, player0_.balance as balance1_4_, player0_.birth as birth2_4_, player0_.currency as currency3_4_, player0_.name as name4_4_ from player player0_ inner join user player0_1_ on player0_.id=player0_1_.id where player0_.name=?

14:24:02.087 [main] INFO  o.s.b.a.l.ConditionEvaluationReportLoggingListener - 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
14:24:02.103 [main] ERROR o.s.boot.SpringApplication - Application run failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:787)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:768)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
    at com....Application.main(..Application.java:13)
Caused by: java.lang.NullPointerException: null
    at com.....view.ConsoleView.printWelcomeMassege(ConsoleView.java:101)
    at com.....App.createPersone(App.java:46)
    at com.....App.play(App.java:33)
    at com....Application.lambda$0(..Application.java:22)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:784)
    ... 5 common frames omitted
14:24:02.118 [main] INFO  o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'
14:24:02.118 [main] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
14:24:02.165 [main] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.

Как я могу справиться с этим?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2020

Почему объект сущности будет отсоединен после того, как метод вернет его?

Поскольку служба не объявлена ​​транзакционной.

Попробуйте:

@Service
**@Transactional**
public class Service {

    @Autowired
    private PersonRepository personRepository;

    public Person findPersonByName(String name) {
        return personRepository.findByName(name); // System.out.println(person.name) -> someone
    }
}

или

@Service
public class Service {

    @Autowired
    private PersonRepository personRepository;

    **@Transactional**
    public Person findPersonByName(String name) {
        return personRepository.findByName(name); // System.out.println(person.name) -> someone
    }
}

Чтобы уменьшить количество аннотаций и снизить риск их забвения, вы также можете использовать пользовательскую аннотацию TransactionalService :

**@TransactionalService**
public class Service {

    @Autowired
    private PersonRepository personRepository;

    public Person findPersonByName(String name) {
        return personRepository.findByName(name); // System.out.println(person.name) -> someone
    }
}

TransactionalService также настроен на откат для BusinessException и его подклассов.

Библиотека, Drombler Commons , является OpenSource и доступна из Maven Central:

<dependency>
  <groupId>org.drombler.commons</groupId>
  <artifactId>drombler-commons-spring-transaction</artifactId>
  <version>1.0</version>
</dependency>

Обратите внимание, что отсоединение сущностей не делает их нулевыми. Вы действительно получаете исключение NullPointerException при доступе к свойству name? Это будет означать, что объект не может быть найден.

Но из вашего примера кода видно, что вы получаете исключение NullPointerException от доступа к неинициализированной службе.

Вам необходимо автоматически подключить службу в приложении класс, чтобы избавиться от NullPointerException:

**// Some spring annotation**
public class App {

    **@Autowired**
    private Service service;

    public void doSomething(){
        Person person = service.findPersonByName("someone"); 
        // System.out.println(person.name) -> nullpointerEx
    }
} 
0 голосов
/ 21 февраля 2020

Я думаю, вам не хватает @Column(name = "name") Аннотация

...