后端框架學習筆記


1.運行過程

WishList(Domain)-->WishListMapper(DAO)-->WishListService(Service)-->WishListController(Controller)
以上是從原型定義到mybatis的Mapper文件定義,再到提供服務,然后提供接口和結果的過程。

2.@Param參數

在定義mybatis的mapper文件或者定義基於注解的sql語句時候,使用@Param注解,如下:

@Select("SELECT id, user_id, item_id, add_price, add_time, created, updated FROM" +"user_collection_info WHERE user_id= #{userId} AND item_id= #{itemId, jdbcType=BIGINT}")
List<WishList> getWishListItemByItemId(@Param("userId") long userId, @Param("itemId") long itemId);

@Param后的字段和#{}之中的內容對應,select選擇的是數據庫之中的字段,后面的#{itemId}可以自由命名,只要在@Param之中對應起來就行。

3.IDEA的幾個縮寫

psvm=補全main函數
fori =for循環
sout =System.out.println();

4.接口,參數,請求等之間的關系

接口的請求:接口分為一般接口和分布式接口(如Dubbo接口),一般的隨便調用,Dubbo接口主要是為了在分布式環境下提供服務,可以在不同的機器之間調用(RPC);返回的數據格式:調用了接口之后,返回的數據一般是json格式的,但是其中的具體內容,還需要和前端商討,返回的數據到底是什么格式;參數的傳遞:在Http的Get請求下,所需要的數據可以通過URL上通過http://localhost:8080/wishlist/getMarkList?userId=2&pageSize=10&pageStart=0 ?參數1=值1&參數2=值2&...這種方式為參數賦值,我們可以通過url給controller中調用的方法的參數賦值,此時controller方法參數的名字和url之中的參數的名字要相同,否則取不到值。而對於Http的Post請求,我們是沒法看到對應的頁面的,傳遞參數的方式是一樣的,需要借助工具實現,如postman來發送post請求。一個“悖論”是,我們需要的參數通過url傳遞,但是應該也有其他方式傳遞,比如我提交了注冊按鈕,然后,一般而言不會跳轉到一個新的頁面,應該是直接取到后台返回的結果,然后在本頁刷新即可,也就是說,url在取得參數數據之后這種情況是Post請求的情況,而Get請求是相對應起來的),這種情況是針對於Post請求的,可以把Post請求理解為在后端進行,不需要對應的頁面即可。字段的對應關系:還有在contorller, service, mapper, url和數據庫之中字段的對應關系,mappr和數據庫對應,url和controller對應,其他地方沒有明確的要求,定義統一和方便自己查找即可,對於時間的處理,一般不寫在函數的參數請求之中,而直接在SQL中操作

5.微服務

不能我去查找別人的,我沒有權限的數據庫字段,不是我的模塊,對我而言,我是看不到的,我需要的數據我無法直接獲取的時候,我需要調用別人提供給我的接口,一般而言,我只需要在這些數據之中找到我要的部分,然后將其組裝,就可以了。簡言之:不是我的,我無法直接操作底層(數據庫),只能通過調用別人的提供的接口,來獲取我需要的內容

6.幾個常見的術語

關鍵詞 名稱 術語
api接口 Service接口 service
Model 接口 model
實現類 Mapper 接口 dao
Model POJO類 domain/model
Service/Serviceimpl Service實現類 service
Controller 調用類 controller

7.異常處理和日志

異常處理一般在service層處理,需要處理的時候處理,返回相應的result(一般是Json格式),日志的話一般是使用logback,常量常數的話一般不是直接使用1,0這種表示,而是將其定義為常量,這樣更有含義,明確。

8.數據來源

我自己管理的數據庫表,只有一部分我需要的數據,但是其他的部分在別人的數據庫表之中,我怎么拿到全部我想要的數據呢?一般的思路是這樣的:在分布式的系統和微服務的架構下我無法直接操作別人的數據庫,無法直接通過操作別人數據庫的方式來獲得數據,所以只能通過別人提供的服務接口來獲得數據,然后通過和我自己的一部分數據,通過一定的條件查詢,拼裝組合出我想要的數據。一般而言,在mybatis之中,需要定義好一個組裝成的數據的Model,然后直接將數據填充到Model的對象之中去。

9.IDEA調試快捷鍵

模式 作用
F7 Debug 進入斷點方法之中
F8 Debug 不進入斷點,越過斷點直接給出結果
F9 Debug 恢復程序運行
Alt + F8 Debug 彈出可輸入表達式的計算框
Ctrl + F8 Debug / Common 設置/清除斷點
Shift + F7 Debug 智能步入,會讓你選擇一個進入的方法
Shift + F8 Debug 跳出,恢復程序運行,=F9
Ctrl + Shift + F8 Debug 設置斷點的進入條件
Alt + Shift + F7 Debug 進入嵌套的方法之中

10.IDEA的Debug使用

① 如下圖 Gif 所示,查看所選對象的方法常用有三種方式:

  • 選中對象后,使用快捷鍵 Alt + F8
  • 選中對象后,拖動對象到 Watches
  • 選中對象后,鼠標懸停在對象上 2 秒左右。
  • 想看對象的具體內容,選中之中,使用Ctrl + F1,查看對象具體內容。

img1

img6

② 如下圖 Gif 所示,在彈出表達式輸入框中 IntelliJ IDEA 也是能幫我們智能提示。
img2

③ 如下圖 Gif 所示,當我們需要過掉后面的所有斷點的時候,我們不需要去掉這些斷點,只需要點擊左下角那個小圓點,點擊小圓點之后,所有斷點變成灰色,然后我們再在按快捷鍵 F9 即可過掉當前和后面所有的斷點。
img3

④ 如下圖 Gif 所示,我們可以給斷點設置進入的條件,因為變量 temp3 不等於 200 所以該斷點沒有被進入直接跳過。
img4

⑤ 如 下圖Gif 演示,有時候當我們步入方法體之后,還想回退到方法體外,斷點進入 addNum 方法后,點擊 Drop Frame 按鈕之后,斷點重新回到方法體之外。
img5

11.mybatis 到底要不要寫一對多、一對一關聯?

  • 方法1

    • Dao 層有一對多、一對一關聯
    • Service 層寫業務邏輯
  • 方法2

    • Dao 層不寫一對多、一對一關聯,只提供基本的增刪查改
    • Service 層完成關聯查詢等以及寫業務邏輯

方法1在效率上貌似有優勢,但寫 resultMap 和語句真是不開心
方法2對程序員比較友好,但效率不如方法一,而且 service 層會比較臃腫

12.日志的配置,以及其含義

1.Log4j的配置, 2.log4j的使用--IDEA創建maven項目

13.gitflow簡單的操作

gitflow簡單的操作

14.Spring MVC之中出現:No mapping found for HTTP request with URI

A:關於No mapping found for HTTP request with URI..., DID NOT FIND HANDLER METHOD FOR SPRINGMVC資源文件掃描不到---關於SPRING的那些坑

15.springmvc可以對前台返回json數據,也可以從前台獲取JSON格式的數據, 當然,JSON格式只是最常用的一種格式,還有很多其他的格式,后台給前端返回json數據相對簡單,而前台給后台發送JSON格式數據的時候,就需要注意,我們要使用AJAX來幫助(jquey的ajax)即可.此時,一定要搞清楚方向的問題,是前端發送json數據到后台,所以這個發送時從前端發給后台,就是從前端瀏覽器之中發起請求,在web服務器如tomcat運行的時候,后台會接收到這個請求,獲得參數,然后才去相應的措施.
1.springmvc 接收json對象的兩種方式 , 2.Java運用JSON實現后台與前端分工合作(代碼實例) , 3. SpringMVC——對Ajax的處理(包含 JSON 類型), 4.SpringMVC @RequestBody 處理ajax請求, 5. ajax請求,fastjson報出錯誤:syntax error, expect {, actual error, pos 0, 6.springmvc與fastjson的整合,注解@RequestBody的使用

16.表單form簡介

基本語法

<FORM ACTION="URL" METHOD="GET|POST" ENCTYPE="MIME" TARGET="...">
... ... 
</FORM> 

基本功能
表單在網頁中主要負責的是數據采集功能,一個表單基本由三部分組成

  • 表單標簽:這里面包含了處理表單數據所用 CGI (Common Gateway Interface,通用網關接口)程序的 URL (Uniform Resource Location,統一資源定位符)以及數據提交到服務器的方法.
  • 表單域:包含了文本框、密碼框、隱藏域、多行文本框、復選框、單選框、下拉選擇框和文件上傳框等。
  • 表單按鈕:包括提交按鈕、復位按鈕和一般按鈕;用於將數據傳送到服務器上的CGI腳本或者取消輸入,還可以用表單按鈕來控制其他定義了處理腳本的處理工作.

兩個參數

17.前端和后端的感悟

A:form之中的action,對應的不是一個獲取到的地址, 而是將數據傳送, 然后讓其處理問題的地址, 即push! form之中的表單信息提交給Spring MVC之中RequestMapping之中的url進行處理,是的! 但是,為什么此處沒有獲得那邊傳過來的數據呢??? 其實,意思就是,應該是后端的數據綁定到了前端, 還是說前端的數據傳遞到了后端?---> 我想,肯定是前端的數據,傳到了后端,而傳值得方式,是通過前端和后端都有,但是在后端定義的數據模型,id,來完成的. 就是說,在后端定義了一個模型, key在后端定義好了, 但是value需要前端傳過來, 給后端, 經過后端處理, 然后顯示出來.

18.關於form標簽的path和commandName

form標簽之中的path,commandName(modelAttribute)的來源,path就是我需要的一個值的對應的Domain(Model,POJO)類之中的相應的字段,commandName(modelAttribute)就是在Controller之中定義的Model(ModelMap, ModelAndView)對應的Model的key。此處需要理清楚數據綁定的對象,數據綁定的方向。

19.Spring MVC前后端數據交互

A:1.Spring MVC前后端數據交互總結, 2.Spring MVC 后端獲取前端提交的json格式字符串並直接轉換成control方法對應的參數對象, 3.Spring MVC 傳值方式總結, 4.SpringMVC前端傳值到Controller與Controller中傳值到View解析, 5.Spring 向頁面傳值以及接受頁面傳過來的參數的方式

20.JSP頁面使用a href來跳轉到另一個jsp頁面

A:Spring MVC貌似不支持從一個jsp頁面通過<a href="sss.jsp">的方式跳轉,都要通過controller的方式訪問頁面

21.視圖配置的時候,可以設置多個文件夾嗎?可以配置多種視圖后綴嗎?

A: ViewResolver可以設置多個,不同的ViewResolver類型,需要設置不同的ViewResolver,比如jspViewResolver,htmlViewResolver等。至於某一種視圖的多個文件夾,可以在/WEB-INF/views/之中設置,可以設置到不同級別的文件夾之中,但是這樣不靈活,一般都是返回的時候,返回其父級別的文件夾名,比如之前的為/WEB-INF/views/,返回的時候使用的是return "login",比如修改為/WEB-INF/views/user之后,那就需要使用user/login來返回,寫全就是:return "user/login",如果要訪問其他的,新的網頁,則可以使用“user/XXX”,那么就是同一視圖的多個文件夾的訪問方式,而不同的ViewResolver,一般時將其頁面放在不同的頁面之下。1. springmvc如何設置多視圖器,springmvc 多個 ViewResolver , 2.SpringMVC同時支持多視圖(JSP,Velocity,Freemarker等)的一種思路實現

22.Spring MVC之中form標簽,jstl標簽,sf標簽,el表達式,各自使用在什么地方並且有什么區別?

A:JSTL的全名為:Java Server Pages Standard Tag Library。JSP標准標簽庫,由四個定制標記庫(core、format、xml 和sql)和一對通用標記庫驗證器(ScriptFreeTLV 和 PermittedTaglibsTLV)組成。它實現了迭代和條件判斷、數據管理格式化、XML操作以及數據庫訪問的功能。有了jstl標簽庫和el表達式,我們的 jsp中不需要<%%>的java代碼,提高了程序的可讀性和可維護性

EL(Expression Language)表達式:目的是為了使JSP寫起來更加簡單。語法結構:${expression}; 對象:pageScope、requestScope、sessionScope、applicationScope(訪問順序:page—request—session——application)

form標簽是SpringMVC的核心標簽,如下的表達式中,tablib是我們給此標簽庫設置的名字,可以為任意不重復的名字,當然決定此標簽庫的還是URI,URI唯一決定此標簽庫,所以如下的標簽庫可以叫sf,也可以叫form

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

除了Spring標簽,JSTL標簽,還有Strutsde 標簽等等。而EL表達式只是為了方便使用而存在的

區別還沒有寫

23.Spring MVC的模板技術有哪些?

A:模板技術有JSP, Velocity, freemarker和Thymeleaf模板,JSP開發對於MVC是破壞的,而后面三種是MVC模式的,不會在視圖之中直接寫java代碼,而jsp會寫java代碼,然后編譯成servlet,占用JVM的堆大小,會有GC的產生。Velocity, freemarker和Thymeleaf支持MVC開發模式,前后端分離,之間的差別不是非常大,Spring官方推薦的是Thymeleaf模板淺談jsp、freemarker、velocity區別

24.Spring MVC后端傳給前端值,怎么傳,有哪些方法?

A:

25.Spring MVC前端傳給后端值,怎么傳,有哪些方法?

A:

26.spring的jsp類庫有哪些?<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>的含義和說明

A:taglib之中的prefix是一個必要的參數,這個是自己定義的,可以是任何和已有的標簽縮寫不重復的標簽前綴,但是重點在於后面的URI,這是唯一定位一個標簽庫的方式。 Spring的標簽,有form部分和其他部分,這個form是為了數據綁定而設置的,Spring的標簽,主要是使用form,其他的標簽在tags下面,用的不是很多

27.spring的jsp類庫有哪些?

A:Spring提供了兩個JSP標簽庫,用來幫助定義SpringMVC Web的視圖。其中一個標簽庫會用來渲染HTML表單標簽,是from標簽,這些標簽可以綁定model中的某個屬性。另外一個標簽庫包含了一些工具類標簽,我們隨時都可以非常便利地使用它們。在這兩個標簽庫匯中,表單綁定的標簽庫更加有用。我們更多使用的是表單標簽,表單標簽所在的位置為:
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> ,而工具類標簽為
<%@taglib uri="http://www.springframework.org/tags" prefix="sf"%>。1.SpringMVC入門之七:使用JSP作為視圖, 2.Spring MVC 頁面渲染( render view ), 3.SpringMVC入門之五:渲染Web視圖概述

28: spring form之中的標簽,可以卸載spring:form之外嗎?也就是說,能在form之外單獨應用嗎?

A: 是不能的,spring jsp的表單form標簽之中的子元素,如<form:input>,<form:checkouboxs>等,都是需要在form標簽之下才能起作用的,所以spring jsp的表單form標簽之中的子元素必須要包含在form打的標簽之中,在標簽之外就會報錯

29.Spring MVC的默認視圖解析器是什么?

A:當視圖為jsp的時候,默認的視圖解析器為InternalResourceViewResolver,默認的viewClass為JstlView,一般的配置為:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView />
</bean>

30.為什么通過mybatis執行sql語句,一開始可以成功,但是后續執行返回結果為0?

A:這主要是因為數據太小,而查詢的時候無法直接顯示出來數據的原因,比如,刪除的時候使用id和item_id,在一開始的時候都是1,2,3這種數據,但是購物車id主鍵和商品的id的增長是不同步的,所以就會產生數據不同步的原因,此時的表現是,sql語句可以執行,但是返回受影響的行數結果為0。這類問題大多是由於粗心大意,把字段搞錯了!解決這些問題的方法如下:

  • 查看sql日志
    • 調到debug狀態img
    • 查看參數img
  • sql參數檢查
    img
  • Rap2接口聲明查看
  • mybatis語法測試

31.IDEA突然標紅,怎么處理?

A:一般是由於緩存導致的,表現為各個類都無法識別,但是仍然可以運行,此時只需要清理緩存即可。img

32.mybatis之中動態SQL的作用?
A:當我們使用mybatis對一張表進行的CRUD操作,如果業務簡單,那么SQL語句都比較簡單,如果有比較復雜的業務,我們需要寫復雜的SQL語句,往往需要拼接,而拼接 SQL,稍微不注意,由於引號,空格等缺失可能都會導致錯誤。
那么怎么去解決這個問題呢?就需要使用mybatis的動態SQL,通過if, choose, when, otherwise, trim, where, set, foreach等標簽,可組合成非常靈活的SQL語句,從而在提高 SQL 語句的准確性的同時,也大大提高了開發人員的效率

33.@Results,@Result的作用是什么?
A:@Results, 對應<resultMap>表示的是結果映射的列表,包含了一個特別結果列如何被映射到屬性或字段的詳情。屬性為value,@Result是@Results注解的結果數組之中的一條結果,@Results注解產生一個對應的結果數組。

34.嵌入在mybatis動態SQL語句之中的<script>,<CDATA>等標簽的作用?
A:用script標簽包圍,然后像xml語法一樣書寫,很明顯,在java中寫xml可讀性和維護性太差,尤其當SQL很長時,這樣寫是很痛苦的。 <script>,<CDATA>這些標簽是xml之中的標簽,我們一般寫sql的時候不用這么寫,需要注意標點,連接符等即可。寫簡單的SQL,結果拼接,而不是拼接SQL

    @Select("<script>" +
            "SELECT id,sn,user_id,wechat_id,alipay_id,item_id,item_value,mobile," +
            "oilcard_num,oilcard_name,recharge_value,bean_award_value,payment_value,status," +
            "payment_time,order_time,created,updated " +
            " FROM oilcard_recharge_record "+
            "<where>" +
            "<if test=\"status !=null \"> and status = #{status}</if>" +
            "<if test=\"createdStart !=null \"> and created <![CDATA[ > ]]> #{createdStart}</if>" +
            "<if test=\"createdEnd !=null \"> and created <![CDATA[ < ]]> #{createdEnd}</if>" +
            "</where>" +
            "order by order_time desc " +
            "</script>")
    List<OilCardRechargeRecord> listByStatus(@Param("status") Integer status,
                                             @Param("createdStart") Long createdStart,
                                             @Param("createdEnd") Long createdEnd);

sql中有一些特殊的字符的話,在解析xml文件的時候會被轉義,<CDATA>能避免被轉義mybatis 詳解(五)------動態SQLXML CDATA,"![CDATA[","<script>"這些字符在動態sql的語句之中的作用是:**防止sql里面出現諸如"<"、"&"這種XML非法字符的情況 **,MyBatis動態SQL實現ORDER BY和LIMIT的控制?

注意

有時候,只使用單純的sql語句,在使用動態語句的時候,就會出現無法正確解析SQL的情況,比如說,使用<if>語句的時候,在"<if test=\"topic.status != null\" >status = #{topic.status},</if>"這種情況的時候就會出現問題,所以最外層需要使用<script>包起來。另外status = #{topic.status}這句,不能將#和{}分開,比如status = # {topic.status},這種就會出現錯誤。當if的條件只有一句的時候,后面不能加","。比如有

	// 只有一個參數的時候,不能加逗號","---><if test=\"status !=null\"> status = #{status},</if>
	@Select("<script>"
	        + "SELECT "
            + "id, topic_name, topic_introduce "
            + "FROM  article_topic"
            + "<where>"
			+ "<if test=\"status !=null\"> status = #{status}</if>"
            + "</where>"
            + "</script>")
	List<ArticleTopic> getTopicNumber(@Param("status") int status);

在插入語句之中,也可以使用動態條件,如下:

	// 需要添加<script>,否則無法正確解析<if...>的內容,在insert的時候也可以使用<if...>
	@Insert("<script>"
            + "INSERT INTO "
            + "article_topic (id, topic_name, topic_introduce, sort,"
			+ "<if test=\"topicImg !=null \"> topic_img,</if> "
			+ "<if test=\"topicThumbnail !=null \"> topic_thumbnail,</if> "
            + "status,  created,  updated)"
			+ "VALUES"
            + "(#{id}, #{topicName}, #{topicIntroduce}, #{sort}, "
			+ "<if test=\"topicImg !=null \"> #{topicImg},</if> "
			+ "<if test=\"topicThumbnail !=null \"> #{topicThumbnail},</if> "
            + "#{status}, #{created}, #{updated})"
			+ "</script>")
	@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
	long addTopic(ArticleTopic topic);

一般情況下,更新,插入的時候,需要使用到對象,在此時,我們的字段就需要帶對象的名稱,但是在占位符之中,不需要設置對象名,如下:

	@Update("<script>"
	        + "UPDATE article_topic"
			+ "<set>"
			+ "<if test=\"topic.status !=null\"> status = #{topic.status},</if>"
			+ "<if test=\"topic.updated !=null\"> updated = #{topic.updated},</if>"
			+ "</set>"
			+ "<where>"
			+ "id = #{id}"
			+ "</where>"
	        + "</script>")
	long stickyTopic(@Param("topic") ArticleTopic topic, @Param("id") long id);

35.注解,providersql,mapper.xml等方式的異同?
A:注解,providersql,mapper.xml三種方式都是要產生對應的查詢結果,注解方式更加集中,把DAO方法,SQL語句,集中在了一個Java接口之中,方便,但是每次有改動,必須要完整的改動這個接口文件。
providersql和mapper.xml方式比較相似,providersql方式,將sql語句與DAO方法的接口文件分離,使用反射,提供了sql語句的調用,DAO方法和SQL語句是分離的。
mapper.xml方式同樣是分離的,但是在mapper.xml之中,我們可以定義各種resultMap,可以重復利用,利用效率比較高,但是寫起來比較麻煩。

36:動態sql標簽
A:MyBatis的動態SQL是基於OGNL表達式的,它可以幫助我們方便的在SQL語句中實現某些邏輯。MyBatis中用於實現動態SQL的元素主要有:if, where, set, choose(when,otherwise), trim, foreach. 我們在一般是在可能產生不確定條件的地方使用動態SQL的標簽,如在where, update的set之中使用動態標簽。

if是一個基本的標簽,

<if test="條件"> id=#{id} </if>

也可以if+where組合,

<where>
    <if test="條件1"> id=#{id} </if> 
    <if test="條件2"> name=#{name}</if>
</where>

update的<set> 標簽,

<set>
    <if test="條件1">  id=#{id} </if> 
    <if test="條件2">  name=#{name}</if>
</set>

有時候,我們不想用到所有的查詢條件,只想選擇其中的一個,查詢條件有一個滿足即可,使用 <choose> 標簽可以解決此類問題,類似於Java的switch語句

<where> 
    <choose> 
        <when test="條件1">  id=#{id}  </when> 
        <when test="條件2">  name=#{name}  </when> 
        <otherwise> and age=#{sex}  </otherwise>
    </choose> 
</where>

trim標記是一個格式化的標記,可以完成set或者是where標記的功能,在sql其中,添加了一些如分隔符,前綴后綴等的信息。可以對應更多的情況,而foreach更多的是sql之中的in情況,例如id in(id的一個查詢得到的結果集合)

<select id="selectUserByListId" parameterType="com.ys.vo.UserVo" resultType="com.ys.po.User">
    select * from user
    <where>
        <!--
            collection:指定輸入對象中的集合屬性
            item:每次遍歷生成的對象
            open:開始遍歷時的拼接字符串
            close:結束時拼接的字符串
            separator:遍歷對象之間需要拼接的字符串
            select * from user where 1=1 and (id=1 or id=2 or id=3)
          -->
        <foreach collection="ids" item="id" open="and (" close=")" separator="or">
            id=#{id}
        </foreach>
    </where>
</select>

37:Mybatis的Insert Update和Select Delete語句的注意點

A:當我們使用SQL進行insert和update的時候,在Mybatis之中,使用的是對象,而非一個一個的單獨的參數,在Mapper之中,對應的參數為id和對應的對象,而delete和select的時候大多數使用的是id或者其他合適的條件。Mybatis純注解方式

@Insert("<script>"
        + "INSERT INTO "
        + "article_topic (id, topic_name, topic_introduce, sort,"
        + "<if test=\"topicImg !=null \"> topic_img,</if> "
        + "<if test=\"topicThumbnail !=null \"> topic_thumbnail,</if> "
        + "status,  created,  updated)"
        + "VALUES"
        + "(#{id}, #{topicName}, #{topicIntroduce}, #{sort}, "
        + "<if test=\"topicImg !=null \"> #{topicImg},</if> "
        + "<if test=\"topicThumbnail !=null \"> #{topicThumbnail},</if> "
        + "#{status}, #{created}, #{updated})"
        + "</script>")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
long addTopic(ArticleTopic topic);

上面是Insert語句的情況,在addTopic方法之中,參數是ArticleTopic的對象topic,Update的情況和Insert相同,另外當我們使用SqlProvider的時候,Insert和Update的參數都寫在對應的Values和Set的String參數之中,參數和占位符相對應。如下的示例,分別對應為Mapper文件和SqlProvider文件

@InsertProvider(type = ArticleCommentReviewSqlProvider.class, method = "reviewComment")
long reviewComment(@Param("commentReview") ArticleCommentReview commentReview, @Param("id") long id);

@UpdateProvider(type = ArticleCommentReviewSqlProvider.class, method = "reviewCommentAgain")
long reviewCommentAgain(@Param("commentReview") ArticleCommentReview commentReview, @Param("id") long id);
public String reviewComment(@Param("commentReview") ArticleCommentReview commentReview, @Param("id") long id) {
	//insert時,cloumn和對應的參數都寫在sql.VALUES()之中,參數和占位符一一對應
    SQL sql = new SQL();
    sql.INSERT_INTO("article_comment_review");
    sql.VALUES(
			"comment_id, article_id, reviewer_id, review_detail, review_time,"
                    + " review_result, created, updated",
			"#{commentId}, #{articleId}, #{reviewerId}, #{reviewDetail},#{reviewTime}, "
				   + "#{reviewResult}, #{created}, #{updated}");
	return sql.toString();
}

public String reviewCommentAgain(@Param("commentReview") ArticleCommentReview commentReview, @Param("id") long id) {
	//update時,column和對應的參數都寫在sql.SET之中,參數和占位符一一對應
	SQL sql = new SQL();
	sql.UPDATE("article_comment_review");
	sql.SET("review_detail, review_result", "#{reviewDetail}, #{reviewResult}");
	sql.WHERE("id= #{id}");
	return sql.toString();
}

以上這是在Mapper(DAO層)之中的定義,而在Service層和Controller層,我們還是需要整個完整的參數

38:SQL分頁的問題
A:SQL的分頁,我們可以使用limit關鍵字或者limit&offset兩個關鍵字組合來完成分頁的實現,但是使用這兩個關鍵字的時候是有區別的。示例如下:

1️⃣:僅使用limit關鍵字,limit N只返回符合條件的前N條

###### sql的數據計算是從0開始的,第1條的下標為0) #####
SELECT * FROM article_topic LIMIT 10; # 符合條件的前10條
SELECT * FROM article_topic WHERE id<100 LIMIT 10; # 符合條件的前10條,這句和上面一句的含義相同

2️⃣:使用limit關鍵字,limit M , N跳過M條,返回N條,從第M條開始讀取

SELECT * FROM article_topic LIMIT 2,1; # 跳過2條取出1條數據,LIMIT后面是從第2條開始讀,讀取1條信息,即讀取第2條數據,也就是第三條
SELECT * FROM article_topic LIMIT 8,5; # 跳過8條,取出5條,從第8條開始讀取
SELECT * FROM article_topic WHERE id<100 LIMIT 8,5;

3️⃣:使用limit&offset關鍵字,limit M offset N跳過N條,返回M條,從第N條開始計算

SELECT * FROM article_topic LIMIT 2 OFFSET 1; # 返回2條數據,從第1條開始計算,LIMIT后面跟的是2條數據,OFFSET后面是從第1條開始讀取,即讀取第2,3條
SELECT * FROM article_topic LIMIT 10 OFFSET 5; # 返回10條數據,從第5條開始計算

其中第2️⃣種和第3️⃣種之間的關系是相反的,最好統一使用第三種: limit M offset N, 返回M條(跳過N條),從第N條開始計算。 sql 中 limit 與 limit,offset連用的區別 , SQL 語句的LIMIT的用法

39:sql語句定義和查詢時候的一些問題

A:1️⃣:所有的字段最好不要設置成NULL,可以設置為NOT NULL,為其設置一個默認值,通過DEFAULT xxx
2️⃣:將字段定義為BIGINT,INT等數字的時候,如果其大於0,那么可以加一個UNSIGNED來修飾,這樣就不會有小於0的情況,表示無符號,只有我們認為的大於0的情況存在,沒有負數的存在了
3️⃣:給字段和表添加注釋是一個好習慣COMMENT '創建時間',
4️⃣:在創建數據庫的語句之前,最好加上DROP TABLE IF EXISTS xxx表;
5️⃣:在創建SQL的語句之中,所使用的引號都是單引號---'',而不是雙引號
6️⃣:為了區別SQL語句和我們創建或者查詢的字段,可以把SQL保留字,全部大寫,自定義的表明,數據等小寫
一個創建表的例子

# article_info
DROP TABLE IF EXISTS article_info;
CREATE TABLE article_info (
  id  BIGINT(20) UNSIGNED NOT NULL  AUTO_INCREMENT  COMMENT '主鍵',
  topic_id  BIGINT(20) UNSIGNED NOT NULL  COMMENT '專題id',
  user_id  BIGINT(20) UNSIGNED NOT NULL  COMMENT '編輯人id',
  title  VARCHAR(64)  NOT NULL  COMMENT '標題',
  introduce_detail VARCHAR(64)  NOT NULL  DEFAULT ''  COMMENT '推薦詞',
  author  VARCHAR(64)  NOT NULL  COMMENT '作者',
  content  TEXT  NOT NULL  COMMENT '文章內容',
  main_img  VARCHAR(300)  NOT NULL  DEFAULT '' COMMENT '主圖 url',
  thumbnail_img  VARCHAR(300)  NOT NULL  DEFAULT '' COMMENT '縮略圖url',
  status  TINYINT(4)  NOT NULL  DEFAULT 0 COMMENT '狀態(待審核,通過,不通過,發表,下架)',
  release_time  BIGINT(11)  UNSIGNED NOT NULL  DEFAULT 0 COMMENT '發表時間',
  off_time   BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0  COMMENT '下架時間',
  sort  int UNSIGNED NOT NULL  DEFAULT 0 COMMENT '排序',
  created  BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0  COMMENT '創建時間',
  updated  BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0  COMMENT '更新時間',
  PRIMARY KEY (id),
  INDEX idx_article_info_topic_id  (topic_id),
  INDEX idx_article_info_user_id  (user_id)
)DEFAULT CHARSET = utf8  COMMENT = '文章表';


# article_collect
DROP TABLE IF EXISTS article_collect;
CREATE TABLE article_collect (
  id  BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT  COMMENT ' 主鍵',
  user_id  BIGINT(20) UNSIGNED NOT NULL  COMMENT '用戶id',
  article_id BIGINT(20) UNSIGNED NOT NULL  COMMENT '文章id',
  created  BIGINT(20) UNSIGNED NOT NULL DEFAULT 0  COMMENT '創建時間',
  updated  BIGINT(20) UNSIGNED NOT NULL DEFAULT 0  COMMENT '更新時間',
  PRIMARY KEY (id),
  INDEX idx_article_collect_user_id(user_id),
  INDEX idx_article_collect_article_id(article_id),
  UNIQUE idx_union_unique(user_id,article_id)
)DEFAULT CHARSET = utf8  COMMENT = '文章收藏表';


# article_thumb
DROP TABLE IF EXISTS article_thumb;
CREATE TABLE article_thumb(
  id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  user_id BIGINT(20) UNSIGNED NOT NULL COMMENT '用戶id',
  article_id BIGINT(20) UNSIGNED NOT NULL COMMENT '文章id',
  created BIGINT(11) UNSIGNED DEFAULT 0 COMMENT '創建時間',
  updated BIGINT(11) UNSIGNED DEFAULT 0 COMMENT '更新時間',
  PRIMARY KEY (id),
  INDEX  idx_article_thumb_user_id(user_id),
  INDEX  idx_article_thumb_article_id(article_id)
) DEFAULT CHARSET =utf8 COMMENT = '文章點贊表';


# article_area
DROP TABLE  IF EXISTS article_area;
CREATE TABLE article_area (
  id BIGINT(20) UNSIGNED NOT NULL  AUTO_INCREMENT COMMENT '主鍵',
  area_id BIGINT(20)  UNSIGNED NOT NULL  COMMENT '地區id',
  article_id BIGINT(20) UNSIGNED NOT NULL  COMMENT '文章id',
  created BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '創建時間',
  updated BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '更新時間',
  PRIMARY KEY (id),
  INDEX  idx_article_area_article_id(article_id),
  INDEX  idx_article_area_area_id(area_id)
)DEFAULT CHARSET =utf8 COMMENT ='文章地區表';


# article_review
DROP TABLE IF EXISTS article_review;
CREATE TABLE article_review(
  id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  article_id BIGINT(20) UNSIGNED  NOT NULL COMMENT '文章id',
  reviewer_id BIGINT(20) UNSIGNED NOT NULL COMMENT '審核人id',
  review_detail VARCHAR(200) NOT NULL  DEFAULT '' COMMENT '審核說明',
  review_time BIGINT(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '審核時間',
  review_result TINYINT(4) UNSIGNED NOT NULL  COMMENT '審核結果',
  created BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '創建時間',
  updated BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '更新時間',
  PRIMARY KEY (id),
  INDEX  idx_article_area_article_id(article_id)
)DEFAULT  CHARSET =utf8 COMMENT ='文章審核表';


# article_topic
DROP  TABLE IF EXISTS article_topic;
CREATE  TABLE  article_topic(
  id BIGINT(20) UNSIGNED NOT NULL  AUTO_INCREMENT COMMENT '主鍵',
  topic_name VARCHAR(50) NOT NULL  COMMENT '專題名',
  topic_introduce VARCHAR(200) NOT NULL  DEFAULT '' COMMENT '專題簡介',
  sort int UNSIGNED NOT NULL DEFAULT 0  COMMENT '專題排序',
  topic_img VARCHAR(300) NOT NULL  DEFAULT '' COMMENT '專題主圖片',
  topic_thumbnail VARCHAR(300) NOT NULL  DEFAULT '' COMMENT '專題縮略圖',
  status TINYINT(4) NOT NULL COMMENT '專題狀態',
  created BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '創建時間',
  updated BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '更新時間',
  PRIMARY KEY (id)
)DEFAULT  CHARSET =utf8 COMMENT ='文章主題表';


# article_comment
DROP TABLE  IF EXISTS article_comment;
CREATE TABLE article_comment(
  id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  article_id BIGINT(20) UNSIGNED NOT NULL  COMMENT '文章id',
  user_id BIGINT(20) UNSIGNED NOT NULL  COMMENT '用戶id',
  comment_content VARCHAR(140) NOT NULL COMMENT '評論內容',
  sort int NOT NULL DEFAULT 0  COMMENT '排序',
  status TINYINT(4) NOT NULL COMMENT '狀態(提交,審核通過,不通過',
  created BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '創建時間',
  updated BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '更新時間',
  PRIMARY KEY (id),
  INDEX  idx_article_comment_article_id(article_id),
  INDEX  idx_article_comment_user_id(user_id)
)DEFAULT  CHARSET =utf8 COMMENT ='文章評論表';


# article_comment_thumb
DROP TABLE IF EXISTS article_comment_thumb;
CREATE  TABLE article_comment_thumb(
  id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  comment_id BIGINT(20)  UNSIGNED NOT NULL COMMENT '評論id',
  user_id BIGINT(20) UNSIGNED NOT NULL COMMENT '用戶id',
  created BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '創建時間',
  updated BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '更新時間',
  PRIMARY KEY (id),
  INDEX idx_article_comment_thumb_user_id(user_id),
  INDEX idx_article_comment_thumb_comment_id(comment_id)
)DEFAULT  CHARSET =utf8 COMMENT ='文章評論點贊表';


# article_comment_review
DROP TABLE IF EXISTS article_comment_review;
CREATE TABLE article_comment_review(
  id BIGINT(20) UNSIGNED NOT NULL  AUTO_INCREMENT COMMENT '主鍵',
  comment_id BIGINT(20) UNSIGNED NOT NULL  COMMENT '評論id',
  article_id BIGINT(20) UNSIGNED NOT NULL  COMMENT '文章id',
  reviewer_id BIGINT(20) UNSIGNED NOT NULL COMMENT  '審核人id',
  review_detail VARCHAR(200) NOT NULL  DEFAULT ''  COMMENT '審核說明',
  review_time BIGINT(11) NOT NULL  DEFAULT 0 COMMENT '審核時間',
  review_result TINYINT(4) NOT NULL COMMENT '審核結果',
  created BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '創建時間',
  updated BIGINT(11) UNSIGNED NOT NULL  DEFAULT 0 COMMENT '更新時間',
  PRIMARY KEY (id),
  INDEX idx_article_comment_review_reviewer_id(reviewer_id)
)DEFAULT  CHARSET =utf8 COMMENT ='文章評論審核表';

39:MySQL字段的疑惑

A:mysql之中的bigint長度為8個字節int為4個字節,tinyint為1個字節,不同類型的int決定了存儲的占用的字節數量,而經常使用的tinyint(M):M默認為4,SMALLINT(M):M默認為6,MEDIUMINT(M):M默認為9,INT(M):M默認為11,BIGINT(M):M默認為20。**M表示最大顯示寬度,建表若設置了zerofill(0填充),會在數字前面補充0 **。

他山之石:

不是我們有這種限制,所有的建表都要加上這個限制 這個含義和入參檢查是一樣的,不是可以保存多大的值就保存多大的值,要從邏輯入手,性別就1位,身份證就17位,手機號就11位

40:MVC模式在何處進行數據校驗

A:一般java web的項目分為domain, dao, service, controller等層,數據的校驗和參數傳遞集中在controller和service兩個地方,具有較大的可選性,有兩種方式,1️⃣一種是在service之中獲取基本數據,取得需要的基本數據,在controller層之中進行數據合法性的校驗,然后在此處,將所有的數據統一處理,打包成需要的格式,傳送給前端;2️⃣第二種是在service層之中將所有的數據都驗證,整合,將其傳送給controller層,controller只是做一個url轉發的層。這兩種方式在實際上都是可以的,但是由於第2️⃣種方式要講數據多傳送一次,而在service層之中整個合法性校驗,數據的整合,然后又傳送給controller層,這樣操作比較浪費,所以第1️⃣種方式好,service層提供基本的數據,在controller層之中校驗,組裝數據,轉發請求等

41:Java EE需要掌握的技術

  • [ ] Spring(core/ mvc/boot)
  • [ ] mybatis(hibernate)
  • [ ] nosql(redis/mongodb)
  • [ ] RabbitMQ
  • [ ] RPC(Dubbo)
  • [ ] Zookeeper
  • [ ] 配置工具(maven/Apollo)
  • [ ] linux(命令行操作)

42:intellij idea 運行 tomcat,無法進入斷點的問題解決方法

A:這是因為JMX port被占用而出現的問題,解決方法,1️⃣:重啟機器,2️⃣:使用netstat -aon|findstr 1099 找出來1099端口占用的進程,然后通過taskkill -f -pid 3756 殺掉進程,重新運行,即可。其實和無法啟動tomcat服務器的原因是一樣的。啟動tomcat時jmx port被占用intellij idea 運行 tomcat,無法進入斷點的問題解決方法
img

43:RPC與RMI的介紹

A:RPC(Remote Procedure Call Protocol)遠程過程調用協議,通過網絡從遠程計算機上請求調用某種服務。RMI是遠程方法調用(Remote Method Invocation)。能夠讓在客戶端Java虛擬機上的對象像調用本地對象一樣調用服務端java 虛擬機中的對象上的方法。 RMI中是通過在客戶端的Stub對象作為遠程接口進行遠程方法的調用每個遠程方法都具有方法簽名。如果一個方法在服務器上執行,但是沒有相匹配的簽名被添加到這個遠程接口(stub)上,那么這個新方法就不能被RMI客戶方所調用RPC中是通過網絡服務協議向遠程主機發送請求,請求包含了一個參數集和一個文本值,通常形成“classname.methodname(參數集)”的形式。RPC遠程主機就去搜索與之相匹配的類和方法,找到后就執行方法並把結果編碼,通過網絡協議發回。 RMI只用於Java;RPC是網絡服務協議,與操作系統和語言無關

44:Spring配置多個數據源,如何使用?

A:Spring配置多個數據源的時候,啟用他需要使用包掃描,意思就是在特定的包下面使用某一個特定的數據源,在這個包下的操作,就是用這些對應的數據源。注意:需要單獨把相關的dao創建一個包,放在原先的dao下面會被覆蓋,從而導致無法取到數據源的連接。另外,需要在工程的配置文件之中添加上多個數據源的連接基本信息,方可操作。

@Configuration
@ConfigurationProperties(prefix = "redpacket.datasource")
@MapperScan(basePackages = "com.yjf.redpacketdao", sqlSessionFactoryRef = "redpacketSession")
@EnableTransactionManagement
public class RedPacketDataConfiguration {

	//單獨把相關的dao創建一個包,放在原先的dao下面會被覆蓋,原先的包為com.yjf.dao
	private static final String DATA_SOURCE = "redpacket_ds";

	@Value("${redpacket.datasource.mapUnderscoreToCamelCase}")
	private Boolean mapUnderscoreToCamelCase;

	@Bean("redpacketSession")
	public SqlSessionFactory getSqlSessionFactory(@Qualifier(DATA_SOURCE) DataSource ds) throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(ds);
		org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
		configuration.setMapUnderscoreToCamelCase(mapUnderscoreToCamelCase);
		bean.setConfiguration(configuration);
		return bean.getObject();
	}

	@Bean(name = DATA_SOURCE)
	@ConfigurationProperties(prefix = "redpacket.datasource")
	public DataSource dataSourceRedpacket() {
		return DruidDataSourceBuilder.create().build();
	}

	@Bean
	public DataSourceTransactionManager redPacketTransactionManager(@Qualifier(DATA_SOURCE) DataSource ds) {
		return new DataSourceTransactionManager(ds);
	}
}

45:把sql的嵌套查詢拆開,應該怎么做?

A:在開發之中,SQL層(Mapper層的查詢),可能經常會遇到多個sql嵌套查詢的情況,這樣的時候,很容易出現Mapper層的耦合,處理這些耦合,就需要把復雜嵌套的sql語句拆分成單獨的簡單的sql,然后在service層之中處理等否,關聯等關系,這樣可以有效減少SQL語句的耦合,讓復雜的SQL變得清晰簡單。

46:寫Mybatis的Mapper文件時候,sql的注意問題?

A:有時候,寫Mapper文件的時候,有時候會有把sql語句都寫在一起,在寫<script>包裹起來的語句,在每一行的sql語句后面,最好后面留一個空格,防止SQL語句拼接連在一起,出現問題

	@Select("<script>"
            + "SELECT "
		   + "id, create_date, ali_user_id, balance, identity_number, is_enabled, is_locked, mobile, name, "
			+ "phone, wx_open_id, member_rank, sinopec_station, real_name, area, "
            + "FROM  member "
			+ "WHERE is_enabled = 1 and is_locked = 0 "
            + "</script>")
	List<Member> getMemberList();

	@Select("<script>"
            + "SELECT "
			+ "id, create_date, ali_user_id, balance, identity_number, is_enabled, is_locked, mobile, name, "
			+ "phone, wx_open_id, member_rank, sinopec_station, real_name, area, "
            + "FROM  member "
            + "WHERE id= #{id}"
			+ "</script>")
	Member getUserById(@Param("id") Long id);

47:需要的數據是從多個表之中獲取,該如何處理?

A:首先我們通過查詢語句,將需要的信息,提取出來,此時我們得到了多種信息,然后接下來,我們可以創建一個新的domain,里面的字段剛好是所需信息的全部字段,然后使用Mapper查詢出來我們要的信息后,在Service層將信息組合,整合出來我們想要的信息,比如,Student表和Book表,student(id, name, age, gender, grade, class, school),book(id, book_name, book_price, book_author, book_detail, book_time, book_type)。如果我們想知道學生喜歡的書籍的類型和出版時間,那么可以新建新的domain,student_book(id, name, age, gender, book_name, book_detail, book_time, book_type),將其組合成一個新的domain, 這樣處理將會方便很多。

ref:

1.IDEA 圖標介紹。 緩存和索引介紹、清理方法和Debug使用, 2.使用 mybatis 到底要不要寫一對多、一對一關聯, 3.Log4j的配置, 4.log4j的使用--IDEA創建maven項目, 5.mybatis 詳解(五)------動態SQL, 6.MyBatis——動態SQL講解, 7.MyBatis注解Annotation介紹及Demo, 8.spring boot(8)-mybatis三種動態sql, 9.mybatis @Select注解中如何拼寫動態sql, 10.MySQL bigint(20)是什么意思?, 11.詳解mysql int類型的長度值問題, 12.Java RMI與RPC的區別, 13.Mybatis純注解方式, 14. sql 中 limit 與 limit,offset連用的區別 , 15.SQL 語句的LIMIT的用法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM