What I am trying to do is to use autowired Spring Service in my UserType. The problem is (as I believe) that Hibernate uses AuthorType.INSTANCE, and it's constructed with no parameters, meaning that field BookShelfService is null.
Is there any way to fix it?
PersonType (extends CommonType which implements UserType):
@Component
public class PersonType extends CommonType {
public static final PersonType INSTANCE = new PersonType();
private BookShelfService shelfService;
@Autowired
public void setShelfService(BookShelfService shelfService) {
this.shelfService = shelfService;
System.out.println("BSS is SET in "+ this);
}
public PersonType() {
super(Person.class);
System.out.println("PT instd: "+this);
}
@Override
public int[] sqlTypes() {
return new int[] {LongType.INSTANCE.sqlType()};
}
@Override
public Object nullSafeGet(ResultSet resultSet,
String[] strings,
SharedSessionContractImplementor sharedSessionContractImplementor,
Object o) throws HibernateException, SQLException {
long id = Long.parseLong(resultSet.getString(strings[0]));
System.out.println("BSS in " + this + ": "+shelfService);
Optional<Person> person = shelfService.findPersonById(id); ** NullPointerException HERE **
if (person.isPresent()) {
return person;
} else throw new IllegalArgumentException("SEVERE: No Person found with id: "+id);
}
@Override
public void nullSafeSet(PreparedStatement preparedStatement,
Object o, int i,
SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException {
if (o == null) {
preparedStatement.setNull(i, LongType.INSTANCE.sqlType());
} else {
preparedStatement.setLong(i, ((Person) o).getId());
}
}
}
BookShelfService:
@Service
public class BookShelfService {
private BooksRepository booksRepository;
private AuthorsRepository authorsRepository;
private BookOwnersRepository bookOwnersRepository;
private PeopleRepository peopleRepository;
@Autowired
public BookShelfService(BooksRepository booksRepository,
AuthorsRepository authorsRepository,
BookOwnersRepository bookOwnersRepository,
PeopleRepository peopleRepository) {
this.booksRepository = booksRepository;
this.authorsRepository = authorsRepository;
this.bookOwnersRepository = bookOwnersRepository;
this.peopleRepository = peopleRepository;
}
public BookShelfService() {
}
public List<Book> findBooksByAuthorNameAndSurname(String name, String surname) {
Optional<Person> person = peopleRepository.findPersonByNameAndSurname(name, surname);
if (!person.isPresent())
throw new IllegalArgumentException("No Person found with name: " + name + ", surname: " + surname);
Optional<Author> author = authorsRepository.findAuthorByPerson(person.get());
if (!author.isPresent())
throw new IllegalArgumentException("No Author found with name: " + name + ", surname: " + surname);
return booksRepository.findBooksByAuthor(author.get());
}
// *** etc.
}
Error:
Exception in thread "main" java.lang.NullPointerException
at bookshelf.jpa.type.PersonType.nullSafeGet(PersonType.java:47)
at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:119)
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:91)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:3041)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1866)
at org.hibernate.loader.Loader.hydrateEntityState(Loader.java:1794)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1767)
at org.hibernate.loader.Loader.getRow(Loader.java:1615)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:745)
at org.hibernate.loader.Loader.processResultSet(Loader.java:1008)
at org.hibernate.loader.Loader.doQuery(Loader.java:964)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
at org.hibernate.loader.Loader.doList(Loader.java:2815)
at org.hibernate.loader.Loader.doList(Loader.java:2797)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2629)
at org.hibernate.loader.Loader.list(Loader.java:2624)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:396)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1396)
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1558)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1526)
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1574)
at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:111)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:409)
at com.sun.proxy.$Proxy83.getSingleResult(Unknown Source)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:196)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:618)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:149)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy76.findAuthorByPerson(Unknown Source)
at bookshelf.jpa.service.BookShelfService.findBooksByAuthorNameAndSurname(BookShelfService.java:62)
at bookshelf.Application.findBlochBooks(Application.java:53)
at bookshelf.Application.main(Application.java:48)
By the way, I noticed that AuthorType gets instantiated in my case 18 times and the 6th in the output list is always the one that is used and produces NullPointerException.