Java for Web學習筆記(一一四):Spring Data(2)倉庫介面__Java

來源:互聯網
上載者:User
查詢方法

CrudRepository中只定義了通過主鍵查詢的方式,這顯然不能滿足需求。Spring提供了查詢方法來解決這樣問題。查詢方法包括: find...By get...By read...By

將返回單個結果T,或者多個結果Iterable<T>, List<T>, Collection<T>,Page<T>。下面是例子:

public interface BookRepository extends PagingAndSortingRepository<Book, Long>{    // 在PagingAndSortingRepository外增加三個查詢方法,對應UNIQUE KEY和KEY的查詢。無需編寫任何實現代碼,Spring data會自動實現的。    Book findByIsbn(String isbn);    List<Book> findByAuthor(String author);    List<Book> findByPublisher(String publisher);      // find...By,By後面的是條件,而find和By之前一般無特定意義,除非是SQL語句中的特定含義     // 中間的Book無意義,只是給方法名字更好的語義,等同於findByIsbn()    Book findBookByIsbn(String isbn);     // 這裡面的distinct作為保留字有意義,Books無意義,相當於SELECT DISTICT * FROM Book Where Publisher=。,    // 假定entity映射的表格為Book,屬性publisher對應的列名了Publisher    List<Book> findDistinctBooksByPublisher(String publisher); }
作者和出版商都可能有很多的書,需要進行分頁處理,我們改為:
public interface BookRepository extends PagingAndSortingRepository<Book, Long>{    Book findByIsbn(String isbn);    Page<Book> findByAuthor(String author, Pageable instructions);    Page<Book> findByPublisher(String publisher, Pageable instructions);}
上面例子中Entity的屬性都是簡單類型,也可以是複雜類型,例如PersonEntity中含有Address address,而Address又具有若干屬性。我們同樣可以通過前面介紹的方式匹配具體的Address,但是如果我們只需要匹配Address裡面的某個屬性,例如郵編。可以寫為:
List<Person> findByAddressPostalCode(PostalCode code); //匹配address屬性裡面的postalCode屬性,這種寫法容易引起歧義,最好採用底線方式Page<Person> findByAddress_PostalCode(PostalCode code, Pageable instructions);
By後面放置查詢條件,我們具體瞭解如何設定:
// ➤ By後面預設是等於,也就是Is或者Equal,下面等同與Book findByIsbn(String isbn); Book findByIsbnIs(String isbn);Book findByIsbnEqual(String isbn);// ➤ NOT,IsNOT表示不等於 List<Book> findByIsbnIsNot(Strign isbn);List<Book> findByIsbnIsNotEqual(Strign isbn);// ➤ OR 和 AND的條件組合 List<Book> findByAuthorAndPublisher(String author, String publisher);List<Book> findByAuthorOrPublisher(String author, String publisher);// ➤ 大小寫不敏感:資料庫中有些列的匹配已經是設定為忽略大小寫,我們也可以在方法中明確聲明。但從查詢效率,我們應答在表格設計中體現,例如某個KEY是大小寫不敏感的。 //只是publisher忽略大小寫List<Book> findByAuthorAndPublisherIgnoreCase(String author, String publisher); //author和publisher忽略大小寫List<Book> findByAuthorIgnoreCaseAndPublisherIgnoreCase(String author, String publisher); //所有均忽略大小寫List<Book> findByAuthorAndPublisherAllIgnoreCase(String author, String publisher); // ➤ After, IsAfter,Befor,IsBefor用於對時間或日期的操作  List<Book> findByDateFoundedIsAfter(Date date);// ➤ 對於%的處理:Contains,Containing, IsContaining,StartsWith,StartingWith, IsStartingWith,EndsWith,EndingWith, IsEndingWith  // 下面相當於WHERE title = '%value%' List<Book> findByTitleContains(String value);// ➤ Like: 下面相當於WHERE title = 'value',注意這和Contain等很相似,但是萬用字元%要放入到value之中 List<Book> findByTitleLike(String value);// ➤ Between,IsBetween List<Book> findByDateFoundedBetween(Date start, Date end);// ➤ Exists:相當於SQL中的EXISTS // ➤ True,IsTrue,False,IsFalse:對boolean的屬性的檢查 List<Book> findByApprovedIsFalse();// ➤ GreaterThan,IsGreaterThan,GreaterThanEqual,IsGreaterThanEqual,LessThan,IsLessThan,LessThanEqual,IsLessThanEqual// ➤ In:表示屬性的值必須等於裡面的某個值,必須採用Iterable來表述 List<Book> findByAuthorIn(Iterable<String> authors);// ➤ Null,IsNull:值為null,方法不應帶有參數,應為已經對值表述清楚 // ➤ Near, IsNear, Within, IsWithin常用於NoSQL,不在JPA中使用 // ➤ Regex,MatchesRegex,Matches用於Regex List<Book> findByTitleRegex(String regex);
自訂的方法

Spring data很強大,但不一定能完全覆蓋我們的需要,在某些情況,我們需要自訂方法。 為某個倉庫提供自訂方法

1、我們定義某個倉庫介面,在裡面提供定義自訂的方法。

public interface TestRepositoryCustom {List<TestEntity> test(int page, int perPageNum, Predicate ... restrictions);}

2、Spring Data的倉庫介面將extends含有自訂的方法的介面

public interface TestRepository extends CrudRepository<TestEntity, Long>,TestRepositoryCustom{TestEntity findByUserName(String userName);}

3、實現自訂的方法。注意,如果這個類無需加上@Repository,但是類名必須為Spring data倉庫介面加上Impl,Spring data掃描到TestRepository後,將會在同一package下面尋找TestRepositoryImpl,如有,將作為Spring bean具體執行個體化(也就是為何我們無需加上@Repository),我們應在此具體實現自訂的方法。至於自訂的介面的名字無任何要求。

public class TestRepositoryImpl implements TestRepositoryCustom{@PersistenceContext private EntityManager entityManager;@Overridepublic List<TestPage> test(int page, int numPerPage, Predicate ... restrictions) {// 具體的代碼 ......}}
為所有倉庫提供自訂方法

這應屬於很罕見的情況,我們需要為所有的倉庫都提供同樣的自訂方法。

1、自訂的介面。這裡extends了JpaRepository(屬於Spring data,其extends了CrudRepository和PagingAndSortingRepository),以便Spring data可以掃描到。標記@NoRepositoryBean是告知Spring data不要為這個介面產生一個實現,因為只是我們通用的自訂介面,不對應具體的倉庫。

@NoRepositoryBeanpublic interface CustomRepository<T, ID extends Serializable> extends JpaRepository<T, ID>{    public void customOperation(T entity);}

2、提供實現,我們必須繼承Spring data JAP提供的基礎倉庫類SimpleJpaRepository。SimpleJpaRepository提供了預定義的介面方法,如findOne(ID),save(T)。如果需要提供Querydsl,則應extends替換為QueryDslJpaRepository。

public class CustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>  implements CustomRepository<T, ID>{    private Class<T> domainClass;    private EntityManager entityManager;    public CustomRepositoryImpl(Class<T> domainClass, EntityManager entityManager){        super(domainClass, entityManager);        this.domainClass = domainClass;        this.entityManager = entityManager;    }    public CustomRepositoryImpl(JpaEntityInformation<T, ?> information,EntityManager entityManager){        super(information, entityManager);        this.domainClass = information.getJavaType();        this.entityManager = entityManager;    }    public void customOperation(T){        // code to implement custom operation    }}

3、讓所有倉庫支援這些自訂的方法。由於我們標記了@NoRepositoryBean,Spring Data JPA不會自動掃描CustomRepositoryImpl,需要建立一個factory bean替代預設的factory bean來完成這項工作,讓掃描倉庫介面後,不將倉庫介面+Impl作為其實現,而指定為CustomRepositoryImpl。

public class CustomRepositoryFactoryBean<R extends JpaRepository<T, ID>, T,ID extends Serializable> extends JpaRepositoryFactoryBean<R, T, ID>{    @Override    protected RepositoryFactorySupport createRepositoryFactory(EntityManager e){        return new CustomRepositoryFactory<T, ID>(e);    }    private static class CustomRepositoryFactory<T, ID extends Serializable> extends JpaRepositoryFactory{        private EntityManager entityManager;        public CustomRepositoryFactory(EntityManager entityManager){            super(entityManager);            this.entityManager = entityManager;        }        @Override        @SuppressWarnings("unchecked")        protected Object getTargetRepository(RepositoryMetadata metadata){            return new CustomRepositoryImpl<T, ID>((Class<T>) metadata.getDomainType(), this.entityManager);        }        @Override        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata){            return CustomRepositoryImpl.class;        }    }}
4、將預設的JpaRepositoryFactoryBean修改為CustomRepositoryFactoryBean
@EnableJpaRepositories(basePackages = "cn.wei.flowingflying.chapter22.site.repositories",    //Returns the FactoryBean class to be used for each repository instance. Defaults to JpaRepositoryFactoryBean.    repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)


相關連結:我的Professional Java for Web Applications相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.