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

https://spring.io/projects/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