JSP、Hibernate、Spring Data JPA
整理工作上用到的知識
JSP
萬萬沒想到JSP這種我以為早就被淘汰的東西,在台灣還有很多企業在用
- JSP的本質其實是Servlet,當它第一次被訪問,透過Web容器(Tomcat)的JSP引擎編譯成Servlet,然後一樣執行init()方法一次,之後開始service(),直到最後被卸載destroy()
- Servlet在Web容器中其實也是編譯成Java,產生.class檔案,當有請求過來就動態的處理一些業務邏輯(例如從request拿參數、去DB撈出對應的資料),最後這個.class用out.print()拼接出封裝好的html的靜態頁面,返回給使用者
- 確實可以在JSP中寫出一個直接捅到JDBC撈資料然後返回的程式碼,但一般來說不會這麼做,而是使用MVC架構
- MVC架構下,訪問發送一個請求過來,轉到Controller,再送到Service層處理業務邏輯,把處理完的資料(可能是某VO)放到pageContext之類的地方,而JSP是作為一個類似模板的地位,用jstl之類的標籤做簡單的邏輯控制、填充要呈現的結果頁面,最後輸出成html給使用者
- 在這種使用框架的情境下,通常用xx.do、xx.action、xx.html等等作為請求的網址,方便Controller區分靜態文件(例如.css或.js)與請求
- JSP的缺點就是它必須依賴Web容器,部署、調試都很麻煩又慢,且Web容器Tomcat在高併發之下成為性能瓶頸,高耦合、難遷移(如果是純html模板那遷移相對容易,JSP就綁死在Java樹上),故JSP技術被淘汰
JPA
Java Persistence API
- 「Java 持久化的 API」,JPA是一個標準規範及接口,通過註解(annotation) 如@Entity、@Table、@Column或XML描述物件-關係表的對映關係,將執行期(在記憶體中)的實體物件持久化到資料庫中
- JPA只是一個標準規範,而要使用JPA的功能就需要Provider來配合,而Provider就是各種ORM框架
- Database - JDBC - JPA - 各種ORM框架
Hibernate
- 全表映射,它把DB與開發者隔離了,可以完全不管DB類型,而使用HQL語句代替,但也是可以用native sql,壞處是性能差,有3種使用模式
- Hibernate Query Language
String hql="select u.uid,u.uname,u.upwd from Users u where u.uname='張三'";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
- 原生SQL查詢,例如:
String sql = "select uid,uname,upwd from _users";
List list = session.createSQLQuery(sql).list();
for(Object obj : list){
System.out.println(obj);
}
- Query By Criteria
- 類似動態語言的特性,可以鏈式查詢
//查詢uname屬性
Criteria criteria = session.createCriteria(Users.class);
PropertyProjection property = Projections.property("name");
criteria.setProjection(property);
List<Object> result = criteria.list();
//查詢uname, upwd屬性
Criteria criteria = session.createCriteria(Users.class);
//1.建立投射列表
ProjectionList projectionList = Projections.projectionList();
//2.向投射列表中新增列投射
PropertyProjection property1 = Projections.property("uname");
PropertyProjection property2 = Projections.property("upwd");
projectionList.add(property1).add(property2);
//3.將投射列表設定到準則中
criteria.setProjection(projectionList);
List<Object> result = criteria.list();
Spring Data JPA
- JPA的進一步封裝,Spring Data JPA底層基於Hibernate,使用註解來宣告Model層,例如
@Entity
@Table(name = "memberaccountjpa")
public class MemberAccountJPA {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="EMAIL")
private String email;
@Column(name="CELLPHONE")
private String cellphone;
@Column(name="PASSWORD")
private String password;
@Column(name="ADDRESS")
private String address;
- 然後造一個對應的XxxRepository介面繼承JpaRepository,就可以快速的使用基礎CRUD,詳細關鍵字看官方文檔
public interface MemberRepository extends JpaRepository<MemberAccountJPA, Long>{
List<MemberAccountJPA> findAll();
List<MemberAccountJPA> findByEmail(String email);
}
- 為何繼承介面就能操作? 底層是動態代理模式,實際執行的實體是SimpleJpaRepository,它執行的方法再往底層追是 hibernate 的CriteriaQueryImpl,拼接出SQL語句
MyBatis
- 不同於傳統ORM,屬於utils系列(沒有完全按照JPA規範),前身是iBatis
- 是半自動映射(指需要手動寫xml提供POJO與DB的映射關係),優勢在於靈活、可優化空間大
- 與Hibernate相比可以看成自排與手排的區別
Mybatis-plus
- 是MyBatis的進一步封裝,優勢在於有類似動態語言的鏈式調用(與Hibernate的Query By Criteria類似,但個人認為Mybatis-plus的更簡潔好用),一般的CRUD都已經封裝好了方法
- 有各種插件提供分頁、自動注入、逆向生成(能連到DB就自動生成POJO與對應的xml mapper),需要複雜的SQL語句時又能直接在xml寫原生SQL語句,算是集簡單易用效能高上限也高的大成,也難怪採用此方案的人越來越多
- 參考筆記 https://yoziming.github.io/post/220112-agg-spring-02-mybatis-plus/
上次修改於 2022-03-01