Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access JpaEntityInformation in custom repository implementation

I have some Spring Data repositories that are extended via fragments as described here. This works fine as long as I only inject the EntityManager in this implementations.

One of those implementations is generic and therefor needs an instance of JpaEntityInformation for the current entity to work correctly (I basically only need the entity name and java type). If I try to "autowire" this in the constructor as well, I get an exception that says that no bean of class JpaEntityInformation could be found.

I understand this exception but I'd like to know whether there is another way to get name and class of the entity the current repository instance was created for. I thought that it should be possible to somehow get the JpaEntityInformation via the constructor because this is the way it is done if you specify a custom repository base class (which I don't want to do).

Below you can find a use case for what I just described.

@NoRepositoryBean
@RequiredArgsConstructor
public class FindByFieldRepositoryImpl<T> implements FindByFieldRepository<T> {

    private final JpaEntityInformation<T, ?> entityInformation;
    private final EntityManager manager;

    @Override
    public T findByField(String field, Object value) {
        return createQuery(field, value).getSingleResult();
    }

    private TypedQuery<T> createQuery(String fieldName, Object fieldValue) {
        String entityName = entityInformation.getEntityName();
        Class<T> entityType = entityInformation.getJavaType();

        String queryString = String.format("FROM %s WHERE %s = :value", entityName, fieldName);
        TypedQuery<T> query = manager.createQuery(queryString, entityType);
        return query.setParameter("value", fieldValue);
    }
}
like image 410
Florian Cramer Avatar asked Oct 04 '17 12:10

Florian Cramer


1 Answers

You can use JpaEntityInformationSupport to get entity information from its class. Here's how your code would look like:

@NoRepositoryBean
@RequiredArgsConstructor
public class FindByFieldRepositoryImpl<T> implements FindByFieldRepository<T> {

    private final EntityManager manager;

    @Override
    public T findByField(String field, Object value, Class<T> clazz) {
        return createQuery(field, value, clazz).getSingleResult();
    }

    private TypedQuery<T> createQuery(String fieldName, Object fieldValue, Class<T> clazz) {
        JpaEntityInformation entityInformation = JpaEntityInformationSupport.getEntityInformation(clazz, manager);
        String entityName = entityInformation.getEntityName();
        Class<T> entityType = entityInformation.getJavaType();

        String queryString = String.format("FROM %s WHERE %s = :value", entityName, fieldName);
        TypedQuery<T> query = manager.createQuery(queryString, entityType);
        return query.setParameter("value", fieldValue);
    }
}

I haven't tested this code but it should work.

like image 135
Mustafa Avatar answered Sep 24 '22 15:09

Mustafa