知識(shí)點(diǎn)1:thymeleaf傳來(lái)的都是String類(lèi)型偶房,轉(zhuǎn)為int類(lèi)型的java語(yǔ)法如下
int user_id = Integer.parseInt(request.getParameter("user_id"));
知識(shí)點(diǎn)2:如果前端的<input>
標(biāo)簽用了diasbled
,則該輸入框的內(nèi)容不僅前端無(wú)法修改眉厨,提交表單時(shí)也無(wú)法傳值到 controller
層
如果只是想在前端對(duì)輸入框input
禁用修改庇勃,但要保持將值傳到后臺(tái)的能力,則 可以使用 readonly
屬性
參考鏈接:
知識(shí)點(diǎn)3:主外鍵表關(guān)聯(lián)時(shí)刪除項(xiàng)時(shí)需要的注意事項(xiàng)
需要先刪除子表(即帶外鍵的表)披摄,再刪除父表(即其主鍵是其它表外鍵的表)
拓展鏈接:
知識(shí)點(diǎn)4:多表聯(lián)查的語(yǔ)句示例
SELECT fc.first_category_id, sc.second_category_id, fc.first_category_name, sc.second_category_name FROM demo.tb_first_category fc LEFT JOIN demo.tb_second_category sc ON fc.first_category_id = sc.second_category_id;
參考鏈接:
圖解MySQL 內(nèi)連接、外連接叼架、左連接畔裕、右連接衣撬、全連接
知識(shí)點(diǎn)5:修改列名稱(chēng)的mysql語(yǔ)句示例
alter table tb_first_category modify name_before_modified name_after_modified unsigned NOT NULL after first_category_id;
參考鏈接
MYSQL數(shù)據(jù)庫(kù)(九)- 修改數(shù)據(jù)表名稱(chēng)乖订、列名稱(chēng)
問(wèn)題6:頁(yè)面切換時(shí)如何傳參
問(wèn)題描述
在一個(gè)index.html
里扮饶,用 thymeleaf
的th:replace
引入了5個(gè)功能模塊的頁(yè)面,切換功能的邏輯是乍构,選中哪個(gè)功能則顯示哪個(gè)功能的頁(yè)面甜无,將其 display
屬性設(shè)為block
, 其它功能模塊的屬性則設(shè)為 none
用 javascript
代碼實(shí)現(xiàn)如下:
function changePage(id){//用于實(shí)現(xiàn)頁(yè)面切換
var parent = document.getElementById("fragParent");
var allFragment=parent.getElementsByClassName("fragment");
console.log(allFragment);
console.log(allFragment.length);
for (var i=0;i < allFragment.length;i++){
if(parseInt(id)==parseInt(i)) {
allFragment[i].style.display = "block";
}
else{
allFragment[i].style.display = "none";
}
}
}
現(xiàn)在的問(wèn)題是,在這樣的切換頁(yè)面思路下哥遮,如何實(shí)現(xiàn)各子頁(yè)面切換時(shí)的數(shù)據(jù)傳遞岂丘。
錯(cuò)誤的思路
一開(kāi)始的思路是寫(xiě)不同的路由,點(diǎn)擊鏈接跳轉(zhuǎn)不同的路由再跳回主頁(yè)眠饮,結(jié)果這樣的邏輯出錯(cuò)了奥帘,因?yàn)槊看翁囟枷喈?dāng)于一次刷新,之前的display
狀態(tài)也就失效了
正確的思路
因?yàn)?個(gè)子頁(yè)面都是在父頁(yè)面里的仪召,只不過(guò)用js
控制了其display
屬性寨蹋,所以應(yīng)該在 index.html
加載的時(shí)候就 將各子頁(yè)面需要變量在index
跳轉(zhuǎn)的controller
層將之全部傳到index
頁(yè)面。
知識(shí)點(diǎn)7:帶條件的多表聯(lián)查更新語(yǔ)句示例
UPDATE demo.tb_first_category fc INNER JOIN tb_second_category sc ON fc.first_category_id = sc.first_category_id SET fc.first_category_name="測(cè)試一級(jí)目錄",sc.second_category_name="測(cè)試二級(jí)目錄" WHERE sc.second_category_id=10
參考鏈接:
mysql 多表 update sql語(yǔ)句總結(jié)
知識(shí)點(diǎn)8:多表關(guān)聯(lián)刪除
下面的語(yǔ)句實(shí)現(xiàn)的功能是刪除id=1
的 table1
表的行扔茅,以及滿(mǎn)足 a.id = b.id
條件的 table2
的對(duì)應(yīng)行
DELETE a,b FROM table1 a INNER JOIN table2 b ON a.id = b.aid WHERE a.id=1
問(wèn)題9:類(lèi)型管理
功能中已旧,點(diǎn)擊特定行的刪除
按鈕,結(jié)果表單提交了錯(cuò)誤的 數(shù)據(jù)行 到后臺(tái)召娜,每次提交的都是列表中第一行
問(wèn)題描述
預(yù)期結(jié)果:
在前端 html
頁(yè)面有一個(gè)數(shù)據(jù)列表运褪,點(diǎn)擊要?jiǎng)h除的數(shù)據(jù)行對(duì)應(yīng)的刪除按鈕,該行對(duì)應(yīng)的表單被提交到后臺(tái)玖瘸,經(jīng)過(guò)后臺(tái)處理后刪除數(shù)據(jù)庫(kù)中對(duì)應(yīng)的信息
實(shí)際結(jié)果:
在前端的列表中秸讹,不管點(diǎn)擊數(shù)據(jù)列表哪一行,表單提交到后臺(tái)controller
層的都是第一行雅倒。
后來(lái)覺(jué)得應(yīng)該是提交時(shí)提交了全部行璃诀,但是變量只能接收第一個(gè)值,所以不管點(diǎn)哪一行后臺(tái)得到的都是第一行的數(shù)據(jù)屯断。
解決方案
之前是將<form>
標(biāo)簽寫(xiě)在了列表標(biāo)簽<ul>
外面文虏,導(dǎo)致相當(dāng)于整個(gè)數(shù)據(jù)列表都是一個(gè)表單里的內(nèi)容了,所以不管點(diǎn)擊哪行的按鈕提交的都是包含了整個(gè)列表內(nèi)容的表單殖演,只要把 <form>
標(biāo)簽放在 <ul>
里氧秘,只包圍每一行數(shù)據(jù)的 li
標(biāo)簽即可
<ul class="list_b" th:each="c : ${categorylist}">
<form method="post" action="/categoryOperation">
<li><input name="second_category_id" th:value="${c.second_category_id}"></li>
<li><input name="first_category_name" th:value="${c.first_category_name}"</li>
<li><input name="second_category_name" th:value="${c.second_category_name}"</li>
</form>
</ul>
問(wèn)題10:實(shí)現(xiàn)提交表單時(shí)利用 confirm()
函數(shù)跳出二次確認(rèn)表單,點(diǎn)擊 確認(rèn)
則提交趴久,點(diǎn)擊 取消
則不提交
直接用 onclick="confirm('確定刪除丸相?');"
是不行的,雖然在彈窗中點(diǎn)擊 確定
確實(shí)會(huì)返回 true
, 點(diǎn)擊 取消
會(huì)返回 false
彼棍,但是返回false
時(shí)依然會(huì)提交表單灭忠,正確的寫(xiě)法應(yīng)該如下:即應(yīng)該在 confirm()
返回 false
時(shí)執(zhí)行return false膳算;
語(yǔ)句:
onclick="if(!confirm('are you ok?')){return false;}"
問(wèn)題11:路由的路徑問(wèn)題
問(wèn)題描述
情況:html
頁(yè)面文件kindadd,html
和其對(duì)應(yīng)的 css
文件 main.css
的目錄結(jié)構(gòu)如下(除了main.css
和kinadd.html
之外其它都是目錄):
templates
--css
----main.css
--EndPages
----kindadd.html
spring boot
中的 application.properties
文件配置的路徑如下:
#默認(rèn)css調(diào)用路徑是static(在resources目錄之后),現(xiàn)在改變其路徑為templates
spring.resources.static-locations=classpath:/templates/
-
如果在
kindAdd.html
中引入樣式表的路徑寫(xiě)為css/main.css
:kindAdd.html
提交的表單的action
屬性設(shè)為/categoryAdd
弛作,控制層的路由也設(shè)為/categoryAdd
控制層函數(shù)處理完
return
的html頁(yè)面路徑 為EndPages/kindAdd
期望結(jié)果是:正確跳轉(zhuǎn)到
.../EndPages/kindAdd.html
實(shí)際結(jié)果是:實(shí)際結(jié)果是跳轉(zhuǎn)到
.../categoryAdd
(注意沒(méi)有html尾綴涕蜂,相當(dāng)于是路由的路徑,這是瀏覽器上顯示的地址映琳,不知道算不算是實(shí)際跳轉(zhuǎn)的地址)机隙,于是加載的css路徑就變?yōu)?code>.../css/main.css, 而正確路徑是.../EndPages/css/main.css
,所以無(wú)法正確加載 -
如果在
kindadd.html
中引入樣式表的路徑寫(xiě)為EndPages/css/main.css
:那么在從別的頁(yè)面(前往該頁(yè)面的路由為/EndPages,其html路徑為/EndPages/index.html) 點(diǎn)擊鏈接跳轉(zhuǎn)到
EndPages/kindAdd.html
的時(shí)候萨西,跳轉(zhuǎn)完畢后加載的css路徑為.../EndPages/EndPages/css/main.css
,導(dǎo)致在這一步的css樣式無(wú)法被正確加載
解決方案
最終我的解決方案是在 kindadd.html
里引用 main.css
的路徑寫(xiě)為 css/main.css
,這樣就不會(huì)在從index.html
跳轉(zhuǎn)過(guò)來(lái)的時(shí)候css加載路徑多一個(gè)EndPages
,同時(shí)為了讓在 kindAdd
提交表單后的跳轉(zhuǎn)能正確加載出css,將其表單提交的action
屬性和對(duì)應(yīng)的路由設(shè)置為EndPages/categoryAdd
//todo: 了解spring boot頁(yè)面和控制層鏈接跳轉(zhuǎn)的邏輯以及css樣式文件引用的相對(duì)邏輯
?
知識(shí)點(diǎn)12: mysql
查詢(xún) SELECT
多條件搜索
直接用AND
或 OR
連接即可,復(fù)合運(yùn)算有歧義時(shí)用括號(hào)括起來(lái)
參考鏈接
知識(shí)點(diǎn)13:帶條件的多表聯(lián)查
(下面這段代碼還是有問(wèn)題有鹿,詳見(jiàn)問(wèn)題14)
SELECT fc.first_category_id, sc.second_category_id, fc.first_category_name, sc.second_category_name FROM demo.tb_first_category fc LEFT JOIN demo.tb_second_category sc ON fc.first_category_id = sc.second_category_id WHERE first_category_name REGEXP "哈哈" OR second_category_name REGEXP "哈哈" limit 9;
注意用LEFT JOIN
左連接,當(dāng)右表沒(méi)有與左表匹配的記錄的時(shí)候也能輸出右表
圖解 mysql 左連接谎脯,右連接葱跋,內(nèi)連接,全外連接
(問(wèn)題其實(shí)是變量寫(xiě)錯(cuò)的問(wèn)題源梭,ON
的條件應(yīng)該是 fc.first_category_id = sc.first_category_id
,最終正確代碼如問(wèn)題15所敘述娱俺。
問(wèn)題14:對(duì)多表聯(lián)查時(shí)出現(xiàn)的問(wèn)題的解決思路
本來(lái)是帶條件的聯(lián)合搜索,排查思路如下:
- 以為是關(guān)聯(lián)表插入時(shí)出現(xiàn)問(wèn)題咸产,結(jié)果去數(shù)據(jù)庫(kù)發(fā)現(xiàn)插入時(shí)是沒(méi)問(wèn)題的
- 后來(lái)發(fā)現(xiàn)搜索時(shí)只能搜索出主表或子表的結(jié)果矢否,想到了應(yīng)該用
LEFT JOIN
而不是INNER JOIN
連接,結(jié)果還是出現(xiàn)以下關(guān)聯(lián)不起來(lái)的問(wèn)題 - 以為是搜索條件設(shè)置不對(duì)脑溢,上網(wǎng)搜了一下將
WHERE
改為AND
,把后面OR
連接的條件用括號(hào)括起來(lái)結(jié)果問(wèn)題更大僵朗,會(huì)搜出很多無(wú)關(guān)的結(jié)果 - 最后把
WHERE
后面的條件全去了發(fā)現(xiàn)還是無(wú)法將兩個(gè)表關(guān)聯(lián)輸出,終于發(fā)現(xiàn)是ON
后面的條件寫(xiě)錯(cuò)了屑彻,應(yīng)該是fc.first_category_id=sc.first_category_id
...
啟示:這段代碼是從上面的多表聯(lián)查的代碼里拷下來(lái)然后添加條件修改的验庙,出現(xiàn)問(wèn)題時(shí)一直以為是后面添加條件導(dǎo)致的問(wèn)題,其實(shí)在上面多表聯(lián)查時(shí)就有這個(gè)問(wèn)題了社牲,然而當(dāng)時(shí)沒(méi)有仔細(xì)檢查結(jié)果粪薛,看到輸出了就以為是對(duì)的了,導(dǎo)致后面debug更難發(fā)現(xiàn)問(wèn)題
結(jié)果first_category_id
最終正確代碼:
SELECT fc.first_category_id, sc.second_category_id, fc.first_category_name, sc.second_category_name FROM demo.tb_first_category fc LEFT JOIN demo.tb_second_category sc ON fc.first_category_id = sc.first_category_id WHERE first_category_name REGEXP #{arg0} OR second_category_name REGEXP #{arg0};
知識(shí)點(diǎn)15: 數(shù)據(jù)庫(kù)查詢(xún)語(yǔ)句的返回類(lèi)型設(shè)置為String
時(shí)搏恤, 只能接受一個(gè)返回值
因?yàn)閿?shù)據(jù)庫(kù)里同一個(gè)name
有多條數(shù)據(jù)违寿,如果用名字搜索的話(huà)會(huì)返回多個(gè)Id
返回的錯(cuò)誤結(jié)果的截圖:
問(wèn)題16 :一個(gè)報(bào)錯(cuò)奇怪的問(wèn)題: 實(shí)際上html中thymeleaf
的語(yǔ)法寫(xiě)錯(cuò)了引起的(也可能是html標(biāo)簽沒(méi)關(guān)閉導(dǎo)致的)
排查思路
在這之前已經(jīng)將controller
層新增的代碼全給注釋掉了,也檢查了index
主頁(yè)的路由發(fā)現(xiàn)也沒(méi)問(wèn)題
在瀏覽器的控制臺(tái)查看錯(cuò)誤說(shuō)找不到一個(gè)定義在index.html
的javascript
函數(shù)熟空,查看源碼往下拉確實(shí)看不到藤巢,把該js
函數(shù)定義放在body
里也不行,由于將代碼跑起來(lái)后再瀏覽器查看的源碼是全部的源碼息罗,包括th:include
的頁(yè)面也一并顯示掂咒,很長(zhǎng),于是想到了是引用的頁(yè)面引起的問(wèn)題
在index
中用 thymeleaf
引用了其它幾個(gè)界面,本來(lái)都沒(méi)什么問(wèn)題绍刮,但是在我修改了其引用的其中一個(gè)頁(yè)面foodlist.html
后温圆,原先在index
定義的</body>
之外</html>
之內(nèi)的js
代碼就識(shí)別不了了,說(shuō)找不到在那定義的函數(shù)孩革,如果把foodlist.html
文件 <body>
里的代碼全注釋了就沒(méi)這么問(wèn)題岁歉,注釋其它引用的頁(yè)面就不行
最后通過(guò)全部注釋?zhuān)鸲稳∠⑨尩姆绞秸业搅藛?wèn)題所在,其實(shí)應(yīng)該能想到的嫉戚,主要修改的就是這一段和另一段刨裆,要出現(xiàn)問(wèn)題最有可能在這兩段澈圈。想到的是 goodlist
的問(wèn)題彬檀,去后臺(tái) debug
發(fā)現(xiàn)果然沒(méi)有取到goodlist
,返回的全為null
這告訴我們一步一debug很重要!
最后發(fā)現(xiàn)的問(wèn)題是entity
層寫(xiě)的對(duì)象的一個(gè)變量名稱(chēng)跟數(shù)據(jù)庫(kù)的變量名不一樣(之前已經(jīng)試過(guò)mysql語(yǔ)句了瞬女,所以只能是在之后的封裝出現(xiàn)問(wèn)題了)
**后來(lái)發(fā)現(xiàn)如果html
頁(yè)面的語(yǔ)法有問(wèn)題窍帝,比如說(shuō)某個(gè)標(biāo)簽少了一半符號(hào)( 如<li
) 也會(huì)報(bào)錯(cuò) **
...
<div class="list_b_c">
<ul class="list_b" th:each="g : ${goodslist}">
<form method="post" action="/brandOperation">
<li class="b20"><input name="commodity_id" th:value="${g.commodity_id}" style="border: none;text-align: center;" readonly="true"></li>
<li class="b20"><input name="cname" th:value="${g.cname}" style="border: none;text-align: center;" readonly="true"></li>
<li class="b20"><input name="name" th:value="${g.name}" style="border: none;text-align: center;" readonly="true"></li>
<li class="b20"><input name="sc_name" th:value="${g.second_category_name}" style="border: none;text-align: center;" readonly="true"></li>
<input type="submit" name="submitInput" value="編輯" class="inputbutton">
<input type="submit" name="submitInput" value="刪除" class="inputbutton" onclick="if(!confirm('are you ok?')){return false;}">
</form>
</ul>
</div>
...
知識(shí)點(diǎn)17:在提交按鈕里寫(xiě)js代碼會(huì)使表單的 required
屬性失效
我在<button>
里添加的 js
代碼是
onclick="alert('保存成功!');"
知識(shí)點(diǎn)18:mysql
GROUP_CONCAT
列表操作
將訂單order_id
與其對(duì)應(yīng)的多個(gè)商品idcommodity_id
以 逗號(hào)連接的字符串
的形式返回
SELECT o.order_id,
o.state,
od.quantity
GROUP_CONCAT(od.commodity_id ORDER BY od.commodity_id) AS commoditys
FROM tb_order o
LEFT JOIN tb_orders_detail od ON o.order_id = od.order_id
GROUP BY o.order_id;
問(wèn)題19:一個(gè)神奇的問(wèn)題,因?yàn)樽詣?dòng)補(bǔ)全了相似的變量名導(dǎo)致一直發(fā)現(xiàn)不了問(wèn)題
這件事告訴我們自動(dòng)補(bǔ)全既能減少因?yàn)樽兞棵l(fā)的bug,也可能導(dǎo)致變量命名引發(fā)的bug诽偷,因?yàn)闀?huì)自動(dòng)補(bǔ)全相似的變量命名反而更難發(fā)現(xiàn)問(wèn)題
寫(xiě)著寫(xiě)著突然dao層掃描不到了坤学,整個(gè) service
層的函數(shù)調(diào)用的dao
層層對(duì)象都出現(xiàn)了紅線(xiàn),于是我就想著肯定是引用或者IDEA本身的問(wèn)題报慕,重啟深浮,查bug都不行,還把dao層對(duì)象刪了重新聲明眠冈,問(wèn)題就在這里飞苇,本來(lái)應(yīng)該是重啟IDEA就解決的,結(jié)果因?yàn)槲抑匦侣暶鱠ao層對(duì)象的時(shí)候IDEA自動(dòng)補(bǔ)全了一個(gè)跟后面用的變量名很像但不是的變量蜗顽,導(dǎo)致問(wèn)題轉(zhuǎn)移了而且因?yàn)橹岸寄苓\(yùn)行我也不會(huì)考慮是變量命名的問(wèn)題布卡,找了一個(gè)小時(shí)找不到來(lái)去吃飯睡了一覺(jué),回到教室再看出現(xiàn)問(wèn)題的地方發(fā)現(xiàn)提醒的問(wèn)題不是說(shuō)原來(lái)的類(lèi)找不到了而是說(shuō)聲明的這個(gè)變量沒(méi)有使用雇盖,然后就發(fā)現(xiàn)我新聲明的變量跟下面使用的不對(duì)應(yīng)....掀凳子.jpg
問(wèn)題20:搞混了插入語(yǔ)句和更新語(yǔ)句忿等,插入語(yǔ)句不能帶條件
如果要更新應(yīng)該用update
,可以帶條件來(lái)更新指定數(shù)據(jù)行崔挖,如果要插入的話(huà)是插入新數(shù)據(jù)贸街,不能帶條件
知識(shí)點(diǎn)21:更新數(shù)據(jù)庫(kù)上某字段的數(shù)值: 在原基礎(chǔ)上增加
update demo.tb_flavor_commodity SET stock=stock+10 WHERE flavor_commodity_id=1;
問(wèn)題22:又一個(gè)神奇的問(wèn)題,因?yàn)樵?code>dao 層的數(shù)據(jù)庫(kù)語(yǔ)句中的mysql
語(yǔ)句寫(xiě)少了個(gè)花括號(hào)狸相,結(jié)果報(bào)路徑錯(cuò)誤...
之前也試過(guò)mysql
語(yǔ)句寫(xiě)錯(cuò)了薛匪,都是能成功運(yùn)行的,只有在訪(fǎng)問(wèn)特定頁(yè)面需要調(diào)用該函數(shù)時(shí)才會(huì)報(bào)錯(cuò)提示mysql
語(yǔ)句錯(cuò)了卷哩,結(jié)果這次直接整個(gè)項(xiàng)目都運(yùn)行不了蛋辈,還報(bào)了一大版的錯(cuò)誤看上去就像是找不到dao
層一樣
最后實(shí)在沒(méi)法了仔細(xì)地看報(bào)錯(cuò)發(fā)現(xiàn)這個(gè)報(bào)錯(cuò)真有特點(diǎn),不是把錯(cuò)誤根源放在前面,而是放在最后面...大概意思是A錯(cuò)了因?yàn)锽錯(cuò)了冷溶,B錯(cuò)了因?yàn)镃錯(cuò)了....最后應(yīng)該是F錯(cuò)了...渐白,而且是一長(zhǎng)句,不拖到最后面根本看不出什么問(wèn)題
mysql
被錯(cuò)誤地寫(xiě)成了如下
...value(#{arg0}),#{arg1,#{arg2}
改正改過(guò)后應(yīng)該是
...value(#{arg0},#{arg1},#{arg2})
報(bào)錯(cuò)信息如下:
2019-07-08 16:44:07.404 WARN 14480 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'endPagesController': Unsatisfied dependency expressed through field 'endpagesservice'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'endPagesServiceImpl': Unsatisfied dependency expressed through field 'endpagesdao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'endPagesDao' defined in file [D:\Git\codehub_download\ShopProject\target\classes\com\example\demo\dao\EndPagesDao.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Could not find value method on SQL annotation. Cause: org.apache.ibatis.builder.BuilderException: Parsing error was found in mapping #{arg1,#{arg2}. Check syntax #{property|(expression), var1=value1, var2=value2, ...}
知識(shí)22:mysql
給表取了別名之后逞频,就不能用原來(lái)的名字了
原來(lái)的代碼
SELECT tb_order.order_id, tb_order.state,tb_order_detail.detail_id,tb_order_detail.quantityGROUP_CONCAT(tb_commodity.cname) FROM tb_order o LEFT JOIN tb_order_detail od ON o.order_id = od.order_id LEFT JOIN tb_commodity c ON od.commodity_id=c.commodity_id GROUP BY o.order_id;
這段 mysql
語(yǔ)句有三個(gè)問(wèn)題:
-
tb_order_detail.quantity
和GROUP_CONCAT
之間應(yīng)該有逗號(hào)隔開(kāi) -
GROUP_CONCAT(tb_commodity.cname)
和FROM
之間應(yīng)該有cname
,并且該cname
之前不能有表名纯衍,即不能是tb_commodity.cname
或cname
,而GROUP_CONCAT()
括號(hào)里的表名可以帶也可以不帶 - 后面
LEFT JOIN
后給三個(gè)表起了別名,所以前面SELECT
的變量的表名也應(yīng)該用別名苗胀,用原名會(huì)報(bào)錯(cuò)
之前我覺(jué)得在變量名前加上表名更嚴(yán)謹(jǐn)避免多個(gè)表中有重名變量襟诸,但是現(xiàn)在發(fā)現(xiàn)有時(shí)候?qū)懕砻粌H是多次一舉的行為,還可能因此引發(fā)錯(cuò)誤基协,比如上面的第2點(diǎn)歌亲,cname就不能帶表名,帶了就報(bào)錯(cuò)
后來(lái)發(fā)現(xiàn)GROUP_CONCAT(c.name) 相當(dāng)于SELECT
出來(lái)的變量名澜驮,所以和前一個(gè)變量應(yīng)該用逗號(hào)隔開(kāi)陷揪。這個(gè) cname
是新變量名,表示GROUP_CONCAT(c.cname)
連接成字符串后的新名稱(chēng)杂穷, 所以不能加表名.
前綴
后來(lái)的代碼
SELECT o.order_id,o.state,od.detail_id,od.quantity, GROUP_CONCAT(c.cname) cname FROM tb_order o LEFT JOIN tb_orders_detail od ON o.order_id = od.order_id LEFT JOIN tb_commodity c ON od.commodity_id=c.commodity_id GROUP BY o.order_id
將od.quantity 也聚合起來(lái)悍缠,并且將兩個(gè)聚合名設(shè)為 quantity_group
, cname_group
:
SELECT o.order_id,o.state,od.detail_id,GROUP_CONCAT(od.quantity) quantity_group, GROUP_CONCAT(c.cname) cname_group FROM tb_order o LEFT JOIN tb_orders_detail od ON o.order_id = od.order_id LEFT JOIN tb_commodity c ON od.commodity_id=c.commodity_id GROUP BY o.order_id
參考鏈接:
MySQL連表操作LEFT JOIN和GROUP_CONCAT函數(shù)分組使用
知識(shí)點(diǎn)23:java的嵌套列表與嵌套數(shù)組
一開(kāi)始時(shí)我是用嵌套列表的,后來(lái)遇到錯(cuò)誤沒(méi)想到是聲明長(zhǎng)度的問(wèn)題就換了二維數(shù)組了耐量,后來(lái)發(fā)現(xiàn)如果只聲明了一維的大小沒(méi)有聲明二維的話(huà)飞蚓,雖然編輯器不會(huì)報(bào)錯(cuò),但是運(yùn)行項(xiàng)目時(shí)會(huì)報(bào)錯(cuò)
如下所示廊蜒,這樣會(huì)出錯(cuò):
//orderlist.size()是一個(gè)列表的長(zhǎng)度趴拧,sgroup.length是一個(gè)數(shù)組的長(zhǎng)度
String[][] arr =new String[orderlist.size()][];
for (int j=0;j<sgroup.length;j++){
arr[i][j]=sgroup[j];//這條語(yǔ)句會(huì)引發(fā)錯(cuò)誤,因?yàn)閍rr[i][j]的第二維長(zhǎng)度沒(méi)有聲明劲藐,相當(dāng)于第二維長(zhǎng)度為0
}
可以聲明時(shí)只初始化行數(shù)八堡,之后再初始化列數(shù)
參考鏈接
java 數(shù)組 聲明時(shí)只初始化行數(shù),之后再初始化列數(shù)的嵌套數(shù)組
知識(shí)點(diǎn)24:thymeleaf
應(yīng)該不可以迭代兩個(gè)對(duì)象(列表/數(shù)組等)
thymeleaf
是可以嵌套迭代的聘芜,但是不可以并列迭代兩個(gè)對(duì)象兄渺,如下所示:在同一個(gè)<ul>
列表中,只迭代orderlist
列表變量或只迭代二維數(shù)組 all_commodity
(嵌套迭代了) 都是可以的汰现,但是這兩個(gè)變量放同一個(gè)<ul>
列表里迭代就會(huì)報(bào)錯(cuò)挂谍。
<ul class="list_b" th:each="o:${orderlist}" th:each="one_order:${all_commodity}">
<li style="width:17%"><input name="cname" th:value="${o.cname_group}" style="width:100%;border: none;text-align: center;" readonly="true"></li>
<select class="form-control" name="name" style="width:100px;margin-left: 210px;">
<option th:each="oo:${one_order}" th:value="${oo}" th:text="${oo}">初始值</option>
</select>
</ul>
知識(shí)點(diǎn)25:英文搜索的技巧:在了解thymeleaf
是否可以迭代兩個(gè)兌現(xiàn)更多過(guò)程中,我在搜了幾次前面的結(jié)果都不是我想要的瞎饲,然后我用英文搜口叙,結(jié)果一搜就出來(lái)了
我的中文搜索關(guān)鍵詞 themeleaf th:each 在同一區(qū)域同時(shí)迭代兩個(gè)對(duì)象
我的英文搜索關(guān)鍵詞thymeleaf th:each iterate two object in one area
第一個(gè)搜索結(jié)果的鏈接如下:
Thymeleaf th:each two iterate two listings - Stack Overflow
里面的答案說(shuō)了thymeleaf
無(wú)法這樣做,變通的方法是把它們放到一個(gè)map
(中文搜索結(jié)果中我看到有提到map
,也想到可能要把這個(gè) list
和 arr
組一個(gè) map
)了嗅战,另外一個(gè)方法就是創(chuàng)建一個(gè)對(duì)象妄田,這個(gè)對(duì)象包含了要迭代的這個(gè)list
和 arr
(這個(gè)方法其實(shí)之前我也想到了俺亮,就是覺(jué)得麻煩)
Unfortunately you cannot do it that way.
Two options that I can think of right now:
- If the lists are of equal size and indexes correspond to same object, put them in a Map and iterate the map. That way you will get the room and roomType
- (Preferred) Create a object and save the room and roomType in it, then add it to single List and iterate the list.
I prefer the second method because you can guarantee what you are actually passing into the list and onto the view layer for processing.
知識(shí)點(diǎn)26:java里的變量聲明問(wèn)題:變量重新賦值后再添加到列表,添加到列表時(shí)沒(méi)有更新變量
其實(shí)變量的聲明和初始化在循環(huán)外的時(shí)候疟呐,每次打印 order_all_in_one.orderOne
也是不一樣的脚曾,即每次循環(huán)的order_all_in_one
都是得到了更新的,但是添加到order_all_in_one_list
后启具,之后再用循環(huán)輸出order_all_in_one_list
的元素又都是一樣的...非常奇怪本讥,把order_all_in_one
的聲明和初始化放在循環(huán)里就沒(méi)這個(gè)問(wèn)題。
后來(lái)發(fā)現(xiàn)變量(可能只是針對(duì)對(duì)象變量)聲明可以在循環(huán)外只聲明一次鲁冯,但是初始化要在循環(huán)內(nèi)拷沸,即每次賦值后,下一次重新賦值前需要重新初始化
List<OrderAllInOneEntity_yrh> order_all_in_one_list=new ArrayList<>();
OrderAllInOneEntity_yrh order_all_in_one;/*只需聲明一次*/
for(int i=0;i<orderlist.size();i++){
order_all_in_one=new OrderAllInOneEntity_yrh();/*該對(duì)象變量每次重新賦值前都要重新初始化*/
order_all_in_one.orderOne=orderlist.get(i);//一個(gè)訂單聚合類(lèi)對(duì)象
//System.out.println("look here!=================");
//System.out.println(order_all_in_one.orderOne);
String one_order_cname=orderlist.get(i).cname_group;//一個(gè)訂單的全部商品:用逗號(hào)連接的字符串
String[] sgroup=one_order_cname.split(",");//每個(gè)訂單的商品切割后存到一個(gè)臨時(shí)數(shù)組中
order_all_in_one.cnameOneLineArr=sgroup;//一個(gè)訂單的全部商品:一維數(shù)組
order_all_in_one_list.add(order_all_in_one);
}