简体   繁体   中英

Spring JPA NoRepositoryBean Queries

How I can use @Query in @NoRepositoryBean methods with @MappedSuperclass ?

I have @MappedSuperclass Temporal (Basis have Long id)

@MappedSuperclass
public abstract class Temporal extends Basis<Long> {

    private Long temporalCode;
    private Date dateBegin;
    private Date dateEnd;
    // getters/setters
}

and @NoRepositoryBean TemporalRepository

@NoRepositoryBean
public interface TemporalRepository<T extends Temporal> extends JpaRepository<T, Long> {
//    this two are ok
    List<T> findByTemporalCode(Long temporalCode);
    List<T> findByTemporalCodeAndDateBeginBeforeAndDateEndAfter(Long temporalCode, Date dateBegin, Date dateEnd);

//    query not working because Temporal is not an @Entity
//    @Query("select t from Temporal t 
//         where (t.dateBegin < ?1 or t.dateBegin is null) 
//         and (t.dateEnd < ?1 or t.dateEnd is null) ")
//    List<T> findByDate(Date date);
}

Update:
For example I have temporal entity Worker:

@Entity
public class Worker extends Temporal {
//    fields and methods here
}

public interface WorkerRepo extends TemporalRepository<Worker> {
//    Looks like it will work but I don't want to write the same method in each TemporalRepository subclass
//    @Query("select w from Worker w where (w.dateBegin < ?1 or w.dateBegin is null) and (w.dateEnd < ?1 or w.dateEnd is null) ")
//    List<Worker> findByDate(Date date);
}

Actualy you could use SpEL expressions for it. Spring Data JPA reference
So we can replace name of superclass with #{#entityName}

Example from reference:

@MappedSuperclass
public abstract class AbstractMappedType {
  …
  String attribute
}

@Entity
public class ConcreteType extends AbstractMappedType { … }

@NoRepositoryBean
public interface MappedTypeRepository<T extends AbstractMappedType>
  extends Repository<T, Long> {

  @Query("select t from #{#entityName} t where t.attribute = ?1")
  List<T> findAllByAttribute(String attribute);
}

public interface ConcreteRepository
  extends MappedTypeRepository<ConcreteType> { … }

Solution for my example:

@NoRepositoryBean
public interface TemporalRepository<T extends Temporal> extends JpaRepository<T, Long> {
    List<T> findByTemporalCode(Long temporalCode);

    List<T> findByTemporalCodeAndDateBeginBeforeAndDateEndAfter(Long temporalCode, Date dateBegin, Date dateEnd);

    @Query("select t from #{#entityName} t 
        where (t.dateBegin < ?1 or t.dateBegin is null)
        and (t.dateEnd < ?1 or t.dateEnd is null)")
    List<T> findByDate(Date dateBegin);
}

KI don't think you can do this because @NoRepositoryBean is used to tell spring that don't create a repository proxy bean for this interface. Such interface is used to expose some additional methods other than concrete repository interface. In that case you have to extend such interface, I will take another example to explain this:

Consider I have Student and Teacher entity :

Now I have interface as:

@NoRepositoryBean
public interface ReadOnlyRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
  T findById(int id);
}

Now we have to write an concrete repo interface like:

public interface StudentRepository extends ReadOnlyRepository<Student, Long> {
  //override the methods of `ReadOnlyRepository` with @query
}

public interface TeacherRepository extends ReadOnlyRepository<Teacher, Long> { 

//override the methods of `ReadOnlyRepository` with @query
}

In this way it's possible to manually define the queries both Student and Teacher by simply declaring JPA named queries Student.findById and Teacher.findById . Using this approach you can easily come up with tailor-made base interfaces for your application scenario.

So @NoRepositoryBean is used to avoid creating repository beans.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM