Struts2_OGNL表達(dá)式
一蝶锋、初步使用ongl表達(dá)式
OGNL是Object Graphic Navigation Language(對(duì)象圖導(dǎo)航語言)的縮寫砚偶,是一個(gè)使用簡單逗旁、功能強(qiáng)大的、開源的表達(dá)式語言(框架),可以方便地操作任何的對(duì)象屬性、方法等揣非。
Struts2框架使用OGNL作為默認(rèn)的表達(dá)式語言,主要用于頁面的取值躲因。它類似于EL表達(dá)式語言早敬,但比EL語法強(qiáng)大很多。
EL Expression Language 表達(dá)式語言大脉, 主要用來獲取 JSP頁面四個(gè)域范圍數(shù)據(jù) (page搞监、 request、 session箱靴、 application )
使用ongl表達(dá)式
1. 導(dǎo)入的jar包:
ognl-xxx.jar : ognl的核心環(huán)境
javassist-xxx.jar : ognl的依賴,提供字節(jié)碼修改能力荷愕。
2. 使用ognl表達(dá)式的jsp頁面需要導(dǎo)入struts2的標(biāo)簽庫
<%@ taglib prefix="s" uri="/struts-tags"%>
3. 幾種基本的使用方式:
1. Java對(duì)象的直接訪問 :
<s:property value="'name'"/><br/>
2. 實(shí)例方法調(diào)用
<s:property value="'name'.length()"/><br/>
3. 賦值操作或表達(dá)式串聯(lián)
<s:property value="1+1" /><br/>
4. 靜態(tài)方法調(diào)用(類的靜態(tài)方法或靜態(tài)變量的訪問) 不推薦
語法:@[類全名(包括包路徑)]@[方法名|值名]
例如:<s:property value="@java.lang.Math@max(10,20)"/><br/>
但是:饣场!安疗!在使用靜態(tài)方法之前必須在struts.xml中開啟靜態(tài)方法調(diào)用功能
<!-- 開啟ognl表達(dá)式靜態(tài)方法調(diào)用 -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
5. OGNL上下文(OGNL Context)和ActionContext的訪問抛杨。(值棧相關(guān)訪問-重要)
6. 集合對(duì)象的操作
二、值棧
值棧的概念
值棧(ValueStack)荐类,是Struts2的數(shù)據(jù)中轉(zhuǎn)站怖现,其中自動(dòng)保存了當(dāng)前Action對(duì)象和其他相關(guān)對(duì)象(包括常用的Web對(duì)象的引用,如request等)玉罐,也可以手動(dòng)保存自己的數(shù)據(jù)對(duì)象屈嗤,同時(shí)也可以隨時(shí)隨地將對(duì)象從值棧取出或操作(通過OGNL表達(dá)式)
了解:值棧的生命周期,和request一樣或action吊输,生命周期都一樣
獲取值棧對(duì)象
在Action動(dòng)作類中獲取值棧對(duì)象有兩種方式:
@Override
public String execute() throws Exception {
//目標(biāo) :獲取值棧對(duì)象
//方式一 : 通過request對(duì)象直接獲取
ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
//方式二 : 通過struts2提供的api來獲取(底層還是1方式)
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
//測試是否是同一個(gè)對(duì)象
System.out.println(valueStack == valueStack2);
return NONE;
}
值棧的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)
在值棧的內(nèi)部有兩個(gè)邏輯部分:
- ObjectStack(對(duì)象棧):保存了Action的相關(guān)對(duì)象和動(dòng)作饶号,數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)是List。
- ContextMap(上下文棧):保存了各種映射關(guān)系季蚂,如常用的web對(duì)象的引用茫船,數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)是Map。
值棧ValueStack(OgnlValueStack實(shí)現(xiàn)類)中有兩塊區(qū)域 :
一塊是CompoundRoot對(duì)象棧(也稱為Root棧),它實(shí)質(zhì)上是使用List集合來存放對(duì)象,存入對(duì)象壓棧從棧頂往下壓扭屁。
一塊是OgnlContext上下文棧(也稱為Map棧)算谈。
Map棧中有兩個(gè)區(qū)域,_root用于存放對(duì)象棧(Root棧)的引用
_values實(shí)質(zhì)上使用Map集合鍵值對(duì)的形式存放對(duì)象
值棧是在請(qǐng)求對(duì)象引用了一塊存儲(chǔ)空間。
值棧包括兩部分: 對(duì)象棧(CompoundRoot料滥,繼承List接口)和OGNL上下文棧(OgnlContext然眼,實(shí)現(xiàn)Map接口)
而OGNL上下文棧內(nèi)部又分為兩部分:對(duì)象棧的引用和一個(gè)HashMap,這個(gè)HashMap會(huì)引用常用web對(duì)象和其他映射關(guān)系葵腹。
三罪治、 操作值棧
棧的概念:
棧是一種數(shù)據(jù)結(jié)構(gòu)丽声,它按照先進(jìn)后出的原則存儲(chǔ)數(shù)據(jù)难裆,即先進(jìn)入的數(shù)據(jù)被壓入棧底呢蛤,
最后進(jìn)入的數(shù)據(jù)在棧頂,需要讀取數(shù)據(jù)的時(shí)候久脯,從棧頂開始彈出數(shù)據(jù)(即最后一個(gè)數(shù)據(jù)被第一個(gè)讀出來)晒骇。
棧也被成為先進(jìn)后出表霉撵,可進(jìn)行插入和刪除操作,插入稱之為進(jìn)棧(壓棧)(push)洪囤,
刪除稱之為退棧(pop)徒坡,允許操作的兩端分別稱為棧頂(top)和棧底(bottom)。棧底固定瘤缩,而棧頂浮動(dòng)喇完。
對(duì)于棧就只能每次訪問它的棧頂元素,從而可以達(dá)到保護(hù)棧頂元素以下的其他元素的目的剥啤。
值棧數(shù)據(jù)的保存:向root棧和map棧放入數(shù)據(jù)
@Override
public String execute() throws Exception {
// 目標(biāo) :向root棧和map棧中分別存入數(shù)據(jù)
String msg = "我愛java";
// 獲取值棧對(duì)象
ValueStack valueStack = ActionContext.getContext().getValueStack();
//向root棧中存值(壓棧),匿名,
valueStack.push(msg);
//root棧中存值(壓棧),有名字
valueStack.set("msg2", "我愛C++");
//向Root棧中存值(鍵值對(duì))
ActionContext.getContext().put("msg3", "我愛Python");
return SUCCESS;
}
通過ognl表達(dá)式取出存儲(chǔ)在值棧中的數(shù)據(jù)顯示在頁面
struts.xml 配置跳轉(zhuǎn)頁面 :
<action name="valueStack2" class="com.itdream.a_valueStack.ValueStack2Action">
<result>/a_ognl/result.jsp</result>
</action>
result.jsp :
<%@ taglib prefix="s" uri="/struts-tags"%>
<!-- 取出存在值棧中的值 -->
<!-- push方法,匿名壓入Root棧的數(shù)據(jù),第一個(gè)被壓入 -->
<s:property value="[1].top"/><br/>
<!-- set方法,Struts2幫我們創(chuàng)建一個(gè)map集合存儲(chǔ)數(shù)據(jù)壓入Root棧的數(shù)據(jù),map的key就是數(shù)據(jù)的名字,通過key取值 -->
<s:property value="msg2"/><br/>
<!-- put方法,放入Map棧中,通過加#號(hào)定向到Map棧中找 -->
<!-- 也可以不加#號(hào)使用默認(rèn)查找機(jī)制,但這樣先從Root棧先找,再到Map棧找key,如果在Root棧找到就找不到Map棧的數(shù)據(jù)了 -->
<s:property value="#msg3"/>|<s:property value="msg3"/><br/>
<!-- 用來查看值棧的內(nèi)容 -->
<s:debug/>
點(diǎn)擊Debug查看值棧的內(nèi)容:
頁面中直接查看值棧的元素的方法锦溪。
struts2為我們提供了一個(gè)標(biāo)簽:<s :debug/>,只要將其加在頁面中即可府怯。
Root棧:
數(shù)據(jù)從棧頂往下壓刻诊,push方法直接壓入String對(duì)象,此時(shí)它是棧頂,索引為0
然后使用set方法,創(chuàng)建了一個(gè)HashMap存儲(chǔ)數(shù)據(jù)的值,作為對(duì)象存入Root棧,此時(shí)棧頂是這個(gè)HashMap對(duì)象,String對(duì)象的索引變?yōu)?
Map棧:
put方法,以鍵值對(duì)形式存儲(chǔ)數(shù)據(jù)
在這里介紹值棧的創(chuàng)建過程:
1. 每次請(qǐng)求都會(huì)創(chuàng)建一個(gè)ActionContext對(duì)象和一個(gè)OnglValueStack值棧對(duì)象,這時(shí)在Root棧中放入了一個(gè)textProvider.
2. 緊接著,Struts2將與Servket有關(guān)的Response,Request,Session等對(duì)象放入到Map棧中,此時(shí)Map棧中有Servlet的對(duì)象引用.
3. 之后就準(zhǔn)備執(zhí)行Action動(dòng)作類 ,創(chuàng)建Action動(dòng)作的代理對(duì)象。Action是在執(zhí)行的時(shí)候才進(jìn)行初始化牺丙,初始化完成后,
將Action對(duì)象壓入Root棧棧頂,并在Map棧的_root中放入一個(gè)引用:key - action
到這里,Root棧中有一個(gè)textProvider與一個(gè)Action對(duì)象,Map棧中有Servlet相關(guān)的數(shù)據(jù)以及Action對(duì)象的引用则涯,
兩個(gè)Action是同一個(gè)
4. 初始化完成,ActionProxy代理對(duì)象在執(zhí)行時(shí),會(huì)先執(zhí)行攔截器冲簿,再執(zhí)行Action,
這個(gè)時(shí)候,如果有Action實(shí)現(xiàn)了ModelDriven接口,模型驅(qū)動(dòng)攔截器就將模型對(duì)象壓入棧頂粟判。
了解原理的目的:
知道值棧的初始化時(shí)機(jī),訪問action的時(shí)候峦剔,才創(chuàng)建(這個(gè)過程中會(huì)創(chuàng)建actionProxy對(duì)象浮入,并且同時(shí)創(chuàng)建值棧,并且羊异,將一些對(duì)象放入值棧事秀。)
值棧初始化之后,里面主要默認(rèn)有:root棧(textProvider野舶、action類對(duì)象易迹、model(user)),map棧(servlet相關(guān)對(duì)象平道、action對(duì)象一個(gè)引用)
哪些對(duì)象在棧頂睹欲!因?yàn)楹竺嫖覀儚闹禇H≈担紡臈m斖氯 K跃酱欢ㄒ滥膫€(gè)對(duì)象在棧上面袋哼。
值棧的默認(rèn)搜索機(jī)制
測試代碼:
public class ValueStack3Action extends ActionSupport {
// 目標(biāo) : 測試值棧的默認(rèn)查找機(jī)制
// 提供Action的屬性,Action初始化完成時(shí),會(huì)將Action的對(duì)象屬性壓入Root棧
private String username = "林志玲";
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String execute() throws Exception {
ValueStack valueStack = ActionContext.getContext().getValueStack();
//在創(chuàng)建一個(gè)有名字的對(duì)象壓入Root棧
valueStack.set("username", "唐嫣");
//往Map棧存入數(shù)據(jù)
ActionContext.getContext().put("username", "高圓圓");
return SUCCESS;
}
}
jsp頁面:
<!-- 取出存在值棧中的值 -->
<s:property value="username"/>
<!-- 用來查看值棧的內(nèi)容 -->
<s:debug/>
此時(shí)運(yùn)行取出username的值是 唐嫣 。
為什么呢闸衫?這是由于值棧的默認(rèn)查找機(jī)制涛贯。
當(dāng)我們使用 對(duì)象名稱 直接查找時(shí),底層使用的API是valuestack.find(ognl)
1. 他會(huì)優(yōu)先從Root棧中開始查找(從上而下),因?yàn)锳ction屬性存入值棧的是在執(zhí)行前壓入的,因此取的時(shí)候,它在值棧的下方,
因此首先找到上面的執(zhí)行時(shí) set 方法放入的 username。
2. 如果Root棧找不到,才會(huì)找Map棧中的key.如果想直接獲取Map棧中的數(shù)據(jù),加個(gè)#號(hào)即可
<s:property value="#username"/>
OGNL操作值棧的幾個(gè)符號(hào):
直接使用對(duì)象名 蔚出, # 弟翘, % , $
1. 直接使用對(duì)象名,使用值棧的默認(rèn)查找機(jī)制
2. #+key 從Map棧中查找對(duì)象的key,從而找到該數(shù)據(jù)
1. 通過#request等可以獲取存儲(chǔ)在Servlet域?qū)ο笾械臄?shù)據(jù)
3. % , 控制解析或者不解析
添加%{'對(duì)象名'}或者'對(duì)象名'讓其變成普通字符串而不解析 骄酗。
<!-- %強(qiáng)制不轉(zhuǎn)換 -->
<s:property value="username"/> <!-- 唐嫣 -->
<s:property value="'username'"/><!-- username -->
<s:property value="%{'username'}"/><!-- username -->
使用%{對(duì)象名}強(qiáng)制解析
<!-- 這里s:textfield標(biāo)簽類似與input的text標(biāo)簽 -->
<s:textfield value="username"/>
<!-- textfield標(biāo)簽的value中直接寫對(duì)象名稱不會(huì)進(jìn)行解析,需要%強(qiáng)制解析 -->
<s:textfield value="%{username}"/>
4. $用于在配置文件中獲取值棧的值
1.URL請(qǐng)求重定向時(shí)稀余,攜帶(動(dòng)態(tài)傳遞)參數(shù) –struts.xml中使用
result type="redirect">/c_expr/ognl2.jsp?name=${myname}</result>
值棧的存取匯總小結(jié)
值棧的主要作用就是數(shù)據(jù)的保存和獲取(可以在任何地方獲惹鞣)睛琳。
1.如何向值棧保存數(shù)據(jù)
-
ValueStack.put(obj)
:保存數(shù)據(jù)到Root棧(棧頂),(對(duì)象本身)匿名,通過索引取出 -
ValueStack.set(key,value)
:保存數(shù)據(jù)到Root棧(棧頂),數(shù)據(jù)被自動(dòng)封裝成一個(gè)Map集合存儲(chǔ),棧頂保存的是一個(gè)Map集合,Map的value就是對(duì)象,這種存儲(chǔ)方式有名字.ognl通過名稱獲取數(shù)據(jù)的值 -
ActionContext.getContext().put(key,value)
: 保存數(shù)據(jù)到Map棧中 - 提供Action成員變量,提供getter方法(Action就在root棧中踏烙,Action屬性可以被搜索)
模型驅(qū)動(dòng)封裝參數(shù)優(yōu)先于屬性驅(qū)動(dòng)的原理:
第四種方式在初始化完成時(shí)壓入Root棧,而ModelDriven過濾器待封裝的參數(shù),在初始化完成后,過濾器中,將其壓入棧頂师骗。
而封裝的參數(shù)從Root棧中取值是自上而下取值的,因此模型驅(qū)動(dòng)優(yōu)先于屬性驅(qū)動(dòng)。
2. ognl表達(dá)式如何獲取值棧的數(shù)據(jù)
- JSP頁面獲取
-
<s :property value= “對(duì)象名”/>
先搜索root棧對(duì)象屬性(getter方法: getXxx-->xxx)宙帝,再搜索map的key -
<s :property value= “#對(duì)象名”/>
搜索map棧的key - 通過
[index].top
指定訪問Root棧的某個(gè)對(duì)象,例如[0].top
訪問棧頂對(duì)象
-
- Action代碼獲取
-
ValueStack.findValue(ognl表達(dá)式)
; 獲取值棧數(shù)據(jù)
-
3. 值棧的生命周期
* 貫穿整個(gè)Action的生命周期丧凤,每個(gè)Action類的對(duì)象實(shí)例都擁有一個(gè)ValueStack對(duì)象募闲。
* Struts2框架將ValueStack對(duì)象保存在名為“struts.valueStack”的請(qǐng)求(request)屬性中步脓,
即值棧是request中的一個(gè)對(duì)象,一個(gè)請(qǐng)求對(duì)應(yīng)一個(gè)Action實(shí)例和一個(gè)值棧對(duì)象浩螺。
因此:值棧的生命周期靴患,就是request生命周期。值棧要出、action鸳君、request生命周期一樣,不存在線程問題患蹂!
重定向跳轉(zhuǎn)頁面時(shí)或颊,目標(biāo)頁面無法獲取到Action中放入值棧的值。
4. 補(bǔ)充,通過EL表達(dá)式獲取值棧的值
EL 表達(dá)式原理:
在page传于、request囱挑、session、application 四個(gè)范圍沼溜,調(diào)用getAttribute 獲取數(shù)據(jù)平挑。為什么也可以獲取值棧的值呢?
原因:Struts2提供StrutsRequestWrapper包裝類,對(duì)request 的 getAttribute 方法增強(qiáng) 通熄。
它優(yōu)先使用 request.getAttribute取值唆涝,如果取不到,執(zhí)行 valueStack的findValue方法使用值棧的默認(rèn)查找機(jī)制唇辨。
問題思考 :
后臺(tái)代碼:
request.setAttribute(“name“, ”aaa“ ) ;//存入request域中
valueStack.set(“name“廊酣,”bbb“ )//存入值棧
頁面代碼:
<s:property name=”name” /> ----- 值棧默認(rèn)查找機(jī)制,bbb
${name} ------ 優(yōu)先從request中查找,aaa
四助泽、CRM案例:添加,顯示,修改客戶
1. 搭建環(huán)境
1.1 搭建Struts2環(huán)境
- 拷貝前端頁面
- 導(dǎo)入Struts2的jar包
- 配置web.xml的前端控制器
- 配置
struts.xml
文件 - Struts2環(huán)境搭建完成
1.2 搭建Hibernate環(huán)境
-
導(dǎo)入
Hibernate
的jar包- required包下的所有jar包
- c3p0的jar包
- 另,log4j-1.x的jar包
刪除
Struts2與Hibernate
沖突的jar包R : 數(shù)據(jù)庫表的編寫
O : 持久化類的編寫
M : 映射文件的編寫
導(dǎo)入日志
log4l.properties
配置文件,創(chuàng)建核心配置文件hibernate.cfg.xml
準(zhǔn)備工具類
HibernateUtils
創(chuàng)建包結(jié)構(gòu),測試Hibernate是否搭建成功
Hibernate
搭建完成
2. 代碼實(shí)現(xiàn)功能
2.1 修改menu.jsp
新增客戶 : 跳轉(zhuǎn)到增加新客戶的頁面
href="${pageContext.request.contextPath }/jsp/customer/add.jsp"
客戶列表 : 查詢所有客戶
href="${pageContext.request.contextPath }/customer_list.action"
2.2 修改add.jsp
form 表單提交路徑 :
action="${pageContext.request.contextPath }/customer_save.action"
2.3 struts.xml
請(qǐng)求與Action的配置關(guān)系
<struts>
<constant name="struts.devMode" value="true" />
<!-- 簡單樣式 -->
<constant name="struts.ui.theme" value="simple"/>
<package name="default" namespace="/" extends="struts-default">
<action name="customer_*" class="com.itdream.crm.web.action.CustomerAction" method="{1}">
<result name="flushListCustomer" type="redirectAction">customer_list.action</result>
<result name="listCustomer">/jsp/customer/list.jsp</result>
<!-- 默認(rèn)轉(zhuǎn)發(fā),傳遞customer數(shù)據(jù) -->
<result name="editjsp">/jsp/customer/edit.jsp</result>
</action>
</package>
</struts>
2.4 Action動(dòng)作類處理請(qǐng)求
1. 提供模型驅(qū)動(dòng),用以封裝參數(shù)啰扛。
2. 查詢到的數(shù)據(jù),存入值棧轉(zhuǎn)發(fā)。
3. 下面是三個(gè)功能:新增客戶,查詢所有客戶,修改客戶
public class CustomerAction extends ActionSupport implements ModelDriven<Customer>{
//提供模型對(duì)象
private Customer customer = new Customer();
@Override
//Struts2獲取模型對(duì)象封裝
public Customer getModel() {
return customer;
}
//添加客戶
public String save() {
//獲取參數(shù),模型驅(qū)動(dòng)自動(dòng)封裝
//調(diào)用業(yè)務(wù)層
CustomerService service = new CustomerServiceImpl();
service.addCustomer(customer);
return "flushListCustomer";
}
//查詢所有客戶
public String list() {
//調(diào)用業(yè)務(wù)層
CustomerService service = new CustomerServiceImpl();
List<Customer> listCustomer = service.findListCustomer();
//將所有Customer的數(shù)據(jù)存入值棧,以set方式存入Root棧
ValueStack valueStack = ActionContext.getContext().getValueStack();
valueStack.set("list", listCustomer);;
//跳轉(zhuǎn)頁面
return "listCustomer";
}
//查詢要修改的客戶,并跳轉(zhuǎn)到修改頁面
public String showEdit() {
//獲取參數(shù)
Long cust_id = customer.getCust_id();
//調(diào)用Service層
CustomerService service = new CustomerServiceImpl();
Customer customer2 = service.findCustomerById(cust_id);
//將查詢到的客戶數(shù)據(jù)壓入值棧
ActionContext.getContext().getValueStack().set("customer", customer2);
//跳轉(zhuǎn)頁面
return "editjsp";
}
//修改客戶信息
public String update() {
//獲取參數(shù)(模型驅(qū)動(dòng))
//調(diào)用業(yè)務(wù)層
System.out.println("hehe");
CustomerService service = new CustomerServiceImpl();
service.updateCustomer(customer);
//跳轉(zhuǎn)
return "flushListCustomer";
}
}
2.5 Service層處理業(yè)務(wù)邏輯
public class CustomerServiceImpl implements CustomerService {
@Override
// 添加客戶
public void addCustomer(Customer customer) {
// 獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
// 開啟事務(wù)
Transaction transaction = session.beginTransaction();
// 業(yè)務(wù)邏輯
try {
CustomerDAO dao = new CustomerDAOImpl();
dao.addCustomer(customer);
} catch (Exception e) {
// struts2默認(rèn)異澄撕兀回滾事務(wù),可以不寫
transaction.rollback();
e.printStackTrace();
} finally {
// 無論是否異常都提交事務(wù)結(jié)束事務(wù)
transaction.commit();
}
}
@Override
// 查詢所有客戶
public List<Customer> findListCustomer() {
// 獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
// 開啟事務(wù)
Transaction transaction = session.beginTransaction();
// 業(yè)務(wù)邏輯
List<Customer> listCustomer = null;
try {
CustomerDAO dao = new CustomerDAOImpl();
listCustomer = dao.findListCustomer();
} catch (Exception e) {
// struts2默認(rèn)異骋猓回滾事務(wù),可以不寫
transaction.rollback();
e.printStackTrace();
} finally {
// 無論是否異常都提交事務(wù)結(jié)束事務(wù)
transaction.commit();
}
return listCustomer;
}
@Override
// 通過id查找客戶
public Customer findCustomerById(Long cust_id) {
// 獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
// 開啟事務(wù)
Transaction transaction = session.beginTransaction();
// 業(yè)務(wù)邏輯
Customer customer = null;
try {
CustomerDAO dao = new CustomerDAOImpl();
customer = dao.findCustomerById(cust_id);
} catch (Exception e) {
e.printStackTrace();
} finally {
transaction.commit();
}
return customer;
}
@Override
// 更新客戶信息
public void updateCustomer(Customer customer) {
// 獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
// 開啟事務(wù)
Transaction transaction = session.beginTransaction();
// 業(yè)務(wù)邏輯
try {
CustomerDAO dao = new CustomerDAOImpl();
dao.updateCustomer(customer);
} catch (Exception e) {
// Struts2默認(rèn)異常回滾
transaction.rollback();
e.printStackTrace();
} finally {
// 提交事務(wù)
transaction.commit();
}
}
}
2.6 dao層操作數(shù)據(jù)庫
1. 添加客戶需要先找到其關(guān)聯(lián)的聯(lián)系人建立關(guān)系
2. 持久態(tài)的使用
public class CustomerDAOImpl implements CustomerDAO {
@Override
//添加客戶
public void addCustomer(Customer customer) {
//獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
//首先找到客戶的聯(lián)系人
//創(chuàng)建Criteria查詢對(duì)象
Criteria criteria = session.createCriteria(Linkman.class);
//創(chuàng)建限制條件
Criterion criterion = Restrictions.eq("lkm_name", customer.getCust_linkman());
//添加限制條件
criteria.add(criterion);
//查詢聯(lián)系人
Linkman linkman = (Linkman) criteria.uniqueResult();
if(linkman == null) {
linkman = new Linkman();
linkman.setLkm_name(customer.getCust_linkman());
}
//保存客戶到數(shù)據(jù)庫
//建立關(guān)系:客戶表達(dá)與聯(lián)系人的關(guān)系:一個(gè)客戶有多個(gè)聯(lián)系人
customer.getLinkmans().add(linkman);
//建立關(guān)系:聯(lián)系人表達(dá)與客戶的關(guān)系:一個(gè)聯(lián)系人對(duì)應(yīng)一個(gè)客戶
linkman.setCustomer(customer);
//將customer變?yōu)槌志脩B(tài),配置了級(jí)聯(lián),會(huì)自動(dòng)級(jí)聯(lián)將linkman也變?yōu)槌志脩B(tài)
session.save(customer);
}
@Override
//查詢所有客戶
public List<Customer> findListCustomer() {
//單表查詢使用Criteria查詢更方便
//獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
//創(chuàng)建Criteria查詢對(duì)象
Criteria criteria = session.createCriteria(Customer.class);
//執(zhí)行查詢
return criteria.list();
}
@Override
//通過ID查詢客戶
public Customer findCustomerById(Long cust_id) {
//獲取Session
Session session = HibernateUtils.getCurrentSession();
//get方法獲取的Customer已經(jīng)是持久態(tài)無需保存
return session.get(Customer.class, cust_id);
}
@Override
//更新客戶信息
public void updateCustomer(Customer customer) {
//獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
//修改客戶
session.update(customer);
}
}
2.7 顯示所有客戶list.jsp
獲取值棧數(shù)據(jù)
<!-- 神奇的request先從request中找,找不到就走值棧的默認(rèn)查找機(jī)制,因此也能查找到存入值棧的list -->
<c:forEach items="${list }" var="customer">
<TR style="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none">
<TD>${customer.cust_name }</TD>
<TD>${customer.cust_level }</TD>
<TD>${customer.cust_source }</TD>
<TD>${customer.cust_linkman }</TD>
<TD>${customer.cust_phone }</TD>
<TD>${customer.cust_mobile }</TD>
<TD>
<a href="${pageContext.request.contextPath }/customer_showEdit.action?cust_id=${customer.cust_id}">修改</a>
</TD>
2.8 edit.jsp
獲取存入值棧的客戶信息,提交修改
form表單action請(qǐng)求地址:
action="${pageContext.request.contextPath }/customer_update.action"
//隱藏域提交客戶id,從而找到該客戶進(jìn)行數(shù)據(jù)更新
<s:textfield name="cust_id" value="%{customer.cust_id}" type="hidden" />
客戶名稱:<s:textfield name="cust_name" value="%{customer.cust_name}" />
客戶級(jí)別:<s:textfield name="cust_level" value="%{customer.cust_level}" />
信息來源:<s:textfield name="cust_source" value="%{customer.cust_source}" />
聯(lián)系人:<s:textfield name="cust_linkman" value="%{customer.cust_linkman}" />
固定電話 :<s:textfield name="cust_phone" value="%{customer.cust_phone}" />
移動(dòng)電話 :<s:textfield name="cust_mobile" value="%{customer.cust_mobile}" />
2.9 功能完成,測試
結(jié)果圖: