1. 概要

Spring Dataを使用すると、リポジトリインターフェイスを定義するだけで、エンティティを操作するプロセスがはるかに簡単になります。 これらには事前定義されたメソッドのセットが付属しており、各インターフェイスにカスタムメソッドを追加することができます。

ただし、すべてのリポジトリで使用できるカスタムメソッドを追加する場合、プロセスは少し複雑になります。 これが、SpringDataJPAを使用してここで検討する内容です。

Spring Data JPAの構成と使用の詳細については、以前の記事「 Spring4を使用したHibernateのガイド」およびSpringDataJPAの概要を参照してください。

2. ベースリポジトリインターフェイスの定義

まず、カスタムメソッドを宣言する新しいインターフェイスを作成する必要があります。

@NoRepositoryBean
public interface ExtendedRepository<T, ID extends Serializable> 
  extends JpaRepository<T, ID> {
 
    public List<T> findByAttributeContainsText(String attributeName, String text);
}

私たちのインターフェースはJpaRepositoryインターフェースを拡張しているので、すべての標準的な振る舞いの恩恵を受けることができます。

@NoRepositoryBeanアノテーションが追加されたことにも気付くでしょう。 これが必要なのは、それ以外の場合、デフォルトのSpringの動作は、Repository。のすべてのサブインターフェイスの実装を作成することであるためです。

ここでは、実際のエンティティ固有のDAOインターフェイスによって拡張されることを意図したインターフェイスにすぎないため、使用する必要のある実装を提供します。

3. 基本クラスの実装

次に、ExtendedRepositoryインターフェースの実装を提供します。

public class ExtendedRepositoryImpl<T, ID extends Serializable>
  extends SimpleJpaRepository<T, ID> implements ExtendedRepository<T, ID> {
    
    private EntityManager entityManager;

    public ExtendedRepositoryImpl(JpaEntityInformation<T, ?> 
      entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
    }

    // ...
}

このクラスは、 SimpleJpaRepository クラスを拡張します。これは、Springがリポジトリインターフェイスの実装を提供するために使用するデフォルトのクラスです。

これには、親クラスからコンストラクターを呼び出すJpaEntityInformationおよびEntityManagerパラメーターを使用してコンストラクターを作成する必要があります。

カスタムメソッドで使用するには、EntityManagerプロパティも必要です。

また、ExtendedRepositoryインターフェースから継承されたカスタムメソッドを実装する必要があります。

@Transactional
public List<T> findByAttributeContainsText(String attributeName, String text) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<T> cQuery = builder.createQuery(getDomainClass());
    Root<T> root = cQuery.from(getDomainClass());
    cQuery
      .select(root)
      .where(builder
        .like(root.<String>get(attributeName), "%" + text + "%"));
    TypedQuery<T> query = entityManager.createQuery(cQuery);
    return query.getResultList();
}

ここで、 findByAttributeContainsText()メソッドは、パラメーターとして指定されたString値を含む特定の属性を持つタイプTのすべてのオブジェクトを検索します。

4. JPA構成

Springに、リポジトリ実装の構築にデフォルトのクラスではなくカスタムクラスを使用するように指示するには、repositoryBaseClass属性を使用できます。

@Configuration
@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao", 
  repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
    // additional JPA Configuration
}

5. エンティティリポジトリの作成

次に、新しいインターフェイスをどのように使用できるかを見てみましょう。

まず、単純なStudentエンティティを追加しましょう。

@Entity
public class Student {

    @Id
    private long id;
    private String name;
    
    // standard constructor, getters, setters
}

次に、ExtendedRepositoryインターフェイスを拡張するStudentエンティティのDAOを作成できます。

public interface ExtendedStudentRepository extends ExtendedRepository<Student, Long> {
}

以上です! これで、実装にはカスタム findByAttributeContainsText()メソッドが含まれます。

同様に、 ExtendedRepository インターフェースを拡張して定義するインターフェースはすべて、同じメソッドを持ちます。

6. リポジトリのテスト

カスタムメソッドの動作を示すJUnitテストを作成しましょう。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { StudentJPAH2Config.class })
public class ExtendedStudentRepositoryIntegrationTest {
 
    @Resource
    private ExtendedStudentRepository extendedStudentRepository;
   
    @Before
    public void setup() {
        Student student = new Student(1, "john");
        extendedStudentRepository.save(student);
        Student student2 = new Student(2, "johnson");
        extendedStudentRepository.save(student2);
        Student student3 = new Student(3, "tom");
        extendedStudentRepository.save(student3);
    }
    
    @Test
    public void givenStudents_whenFindByName_thenOk(){
        List<Student> students 
          = extendedStudentRepository.findByAttributeContainsText("name", "john");
 
        assertEquals("size incorrect", 2, students.size());        
    }
}

このテストでは、最初に extendedStudentRepository Beanを使用して、3つのStudentレコードを作成します。 次に、 findByAttributeContains()メソッドが呼び出され、名前に「john」というテキストが含まれているすべての学生が検索されます。

ExtendedStudentRepository クラスは、 save()などの標準メソッドと追加したカスタムメソッドの両方を使用できます。

7. 結論

このクイック記事では、SpringDataJPAのすべてのリポジトリにカスタムメソッドを追加する方法を示しました。

例の完全なソースコードは、GitHubにあります。