由於自己一個項目要用多到Sql與NoSql兩種截然不同的數據結構,但在編程上我希望統一接口API,讓不同類型的數據庫能在相同的編程接口模式下運作。於是找了一個spring的官網,發現一個spring data的項目。Spring Data 統一所有訪問數據庫的接口,為開發者提供一個更加簡便的開發方式 Spring Data 官網
下面是幾個核心的項目介紹
- Spring Data Commons - 每個Spring Data 項目的核心基礎 (因此每一個Spring Data項目都使用統一的接口)
- Spring Data Gemfire - 以Spring 的方式 提供GemFire 的簡單配置和訪問
- Spring Data JPA - 簡化所有JPA標准數據庫訪問和操作(例如Hibernate MyBatis等等)
- Spring Data KeyValue - 簡化所有以Map結構數據庫及SPIs服務的構建Spring Data 模塊
- Spring Data LDAP - 提供 Spring LDAP.的基礎支持
- Spring Data MongoDB - 為文檔數據庫 構建以Spring 基礎的支持和數據訪問組件
- Spring Data REST - 可以把Spring 數據倉庫 輸出為超媒體的形式的RESTFUL 資源
- Spring Data Redis - 提供簡便的方式訪問Redis
- Spring Data for Apache Cassandra - Apache Cassandra 的 Spring Data 模塊
- Spring Data for Apache Solr - Apache Solr 的 Spring Data 模塊
在Spring Data 以前我們要實現在對一個數據庫的通常是這樣的
我們首先來寫一個接口來說明我們要對數據庫操作什么,然后使用泛型(T)來傳入要保存實體類型,以hibernate為例
public interface CommonDao{ //保存實體 public <T> Serializable save(T entity); //保存或更新實體 public <T> void saveOrUpdate(T entity); //獲取一個實體對象 public <T> get(Class<T> entityName, Serializable id);
}
但我們還要寫一個具體實現類,因為你只是告訴了用戶可以干什么,但沒有告訴后端該怎進行 增刪改查
public CommonDaoImpl implments CommonDao{ //Hibernate Session @Autowired @Qualifier("sessionFactory") private SessionFactory sessionFactory; public Session getSession() { // 事務必須是開啟的(Required),否則獲取不到 return sessionFactory.getCurrentSession(); } public Serializable save(T entity){ try{ Serializable id = getSession().save(entity); getSession().flush(); return id }catch(Exception e){ ........ } } public <T> saveOrUpdate(T entity){ //保存或更新事務代碼 } public <T> get(T entity,Serializable id){ //獲取單個實體代碼 } }
編寫一個數據服務接口,便於隱藏具體實現
public interface CommonService{ // 保存實體 public <T> Serializable save(T entity); // 保存或更新 public <T> void saveOrUpdate(T entity) ;
// 其他數據新增改查方法 }
編寫一個公共數據服務實現類
@Service public class CommonServiceImpl{ //數據訪問接口 @Autowired public CommonDao commonDao; //保存實體實現 public <T> Serializable save(T entity){ //使用數據 commonDao.save(entity); } //保存或更新 public <T> void saveOrUpdate(T entity){ //保存或更新實體 commonDao.saveOrUpdate(entity); } //其他服務方法 }
編寫一個指定模型接口
public interface UserService extends CommonService
{
//繼承父類所有增刪改查接口
//新增接口
public User getMyUser(String id);
public List<User> getUserByUsername(String username);
//.....其他用戶方法
}
對方法進行@Service //用注釋進行組件注入 實現Sprign對接口的管理
public class UserServiceImpl extends CommonServiceImpl implments CommonService{ /**
* 重寫父類保存實體方法
**/ public <T> Serializable save(T entity) { //對User進行前置業務處理 ........ this.save(User(entity));//保存user //返回保存信息 }
/**
* 獲取單個User對象
**/
public User getUser(String id){
this.get(User.class,id);
}
/**
*自定義用戶搜索
**/
public User getUserByUsername(String username){
//定制實現
//hql 實現
//String hql = "from User u where u.password = ? "
// List<User> users = this.queryByHql(password);
//判斷users存不存在
//if(users!=null&&users.size>0)
return users.get(0);
return null;
}
}
這時我們才算實是完成一個完整的數據服務,我們會回顧一下這個編碼步驟
1、編寫數據訪問層通用接口
2、編寫數據訪問層通用實現
3、編寫通用服務接口
4、編寫通用服務實現(包括定制查詢,定制hql 或者 封裝criteria)
5、轉化為pojo
以上就是傳統j2ee crud的編碼過程。
接下來我們要介紹我們今天的主角,Spring-data
看完上面的一堆代碼是不是覺得好煩,為什么呢?因為老子又要寫接口,又要寫實現,寫接口告訴客戶干什么,然后又寫了一個實現告訴java虛擬機要對計算機干什么。這里需要增加了java 的工程性(使用接口把實現和行為本身分開),減輕了使用者的使用成本,也增加了軟件的可維護性擴展性。對於龐大而又復雜的系統來說,這是一個穩健的做發。但是這毫無疑問地增加了開發成本。1、接口和實現本身的代碼量增加。2、需求和設計不明確,導至接口擴展,其實實現也必須擴展。所謂接口就是 java工程的命門。接口的制定者往往是最有經驗的工程師。因為這些東西實在太影響效率了。於是spring-data誕生了。spring-data 的意思是,你只需要在接口里告訴spring你要查詢什么,你要一個什么樣的查詢,它便幫你實現了。你不用自己再去寫查詢語句。不用再拼接復雜的查詢,如果你根據你的姓氏去查詢這個人,你只需要寫,那一切就像變魔術一樣。獲取到一個對象列表
interface PersonRepository extends Repository<Person, Long> { List<Person> findByLastname(String lastname); }
你不用再去寫你dao實現,再見了hql,再見了sql,再見了criteria ,一切來得這么簡潔。到此spring data 為我們做了什么?來我們來回顧一下數據庫與java之前間交互的發展歷程
從圖中可以看我們數據庫操作要解決的問題的一個大概歷程,spring-data實現了重要的一步,把各orm的框架的實現都隱藏掉,把查詢規則和查詢接口統一起來,就是行為即實現,由接口去定義數據庫的查詢實現,而你更不需要關注你使用的是哪個orm框架,因為查詢模型(使用統一接口)和返回模型都是統一的,而orm,查詢封裝這些spring-data通通幫你處理了。
以下為spring-data的接口規則
Logical keyword
Keyword expressions | |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|