




已閱讀5頁(yè),還剩13頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Spring 事務(wù)管理高級(jí)應(yīng)用難點(diǎn)剖析概述Spring 最成功,最吸引人的地方莫過(guò)于輕量級(jí)的聲明式事務(wù)管理,僅此一點(diǎn),它就宣告了重量級(jí) EJB 容器的覆滅。Spring 聲明式事務(wù)管理將開(kāi)發(fā)者從繁復(fù)的事務(wù)管理代碼中解脫出來(lái),專注于業(yè)務(wù)邏輯的開(kāi)發(fā)上,這是一件可以被拿來(lái)頂禮膜拜的事情。但是,世界并未從此消停,開(kāi)發(fā)人員 需要面對(duì)的是層出不窮的應(yīng)用場(chǎng)景,這些場(chǎng)景往往逾越了普通 Spring 技術(shù)書(shū)籍的理想界定。因此,隨著應(yīng)用開(kāi)發(fā)的深入,在使用經(jīng)過(guò) Spring 層層封裝的聲明式事務(wù)時(shí),開(kāi)發(fā)人員越來(lái)越覺(jué)得自己墜入了迷霧,陷入了沼澤,體會(huì)不到外界所宣稱的那種暢快淋漓。本系列文章的目標(biāo)旨在整理并剖析實(shí)際應(yīng)用中 種種讓我們迷茫的場(chǎng)景,讓陽(yáng)光照進(jìn)云遮霧障的山頭。DAO 和事務(wù)管理的牽絆很少有使用 Spring 但不使用 Spring 事務(wù)管理器的應(yīng)用,因此常常有人會(huì)問(wèn):是否用了 Spring,就一定要用 Spring 事務(wù)管理器,否則就無(wú)法進(jìn)行數(shù)據(jù)的持久化操作呢?事務(wù)管理器和 DAO 是什么關(guān)系呢?也 許是 DAO 和事務(wù)管理如影隨行的緣故吧,這個(gè)看似簡(jiǎn)單的問(wèn)題實(shí)實(shí)在在地存在著,從初學(xué)者心中涌出,縈繞在開(kāi)發(fā)老手的腦際。答案當(dāng)然是否定的!我們都知道:事務(wù)管理是 保證數(shù)據(jù)操作的事務(wù)性(即原子性、一致性、隔離性、持久性,也即所謂的 ACID),脫離了事務(wù)性,DAO 照樣可以順利地進(jìn)行數(shù)據(jù)的操作。下面,我們來(lái)看一段使用 Spring JDBC 進(jìn)行數(shù)據(jù)訪問(wèn)的代碼:清單 1. UserJdbcWithoutTransManagerService.java package user.withouttm;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Service;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import mons.dbcp.BasicDataSource;Service(service1)public class UserJdbcWithoutTransManagerService Autowired private JdbcTemplate jdbcTemplate; public void addScore(String userName,int toAdd) String sql = UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?; jdbcTemplate.update(sql,toAdd,userName); public static void main(String args) ApplicationContext ctx = new ClassPathXmlApplicationContext(user/withouttm/jdbcWithoutTransManager.xml); UserJdbcWithoutTransManagerService service = (UserJdbcWithoutTransManagerService)ctx.getBean(service1); JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean(jdbcTemplate); BasicDataSource basicDataSource = (BasicDataSource)jdbcTemplate.getDataSource(); /.檢查數(shù)據(jù)源autoCommit的設(shè)置 System.out.println(autoCommit:+ basicDataSource.getDefaultAutoCommit(); /.插入一條記錄,初始分?jǐn)?shù)為10 jdbcTemplate.execute( INSERT INTO t_user(user_name,password,score) VALUES(tom,123456,10); /.調(diào)用工作在無(wú)事務(wù)環(huán)境下的服務(wù)類方法,將分?jǐn)?shù)添加20分 service.addScore(tom,20); /.查看此時(shí)用戶的分?jǐn)?shù) int score = jdbcTemplate.queryForInt( SELECT score FROM t_user WHERE user_name =tom); System.out.println(score:+score); jdbcTemplate.execute(DELETE FROM t_user WHERE user_name=tom); jdbcWithoutTransManager.xml 的配置文件如下所示:清單 2. jdbcWithoutTransManager.xml 運(yùn)行 UserJdbcWithoutTransManagerService,在控制臺(tái)上打出如下的結(jié)果:defaultAutoCommit:truescore:30在 jdbcWithoutTransManager.xml 中,沒(méi)有配置任何事務(wù)管理器,但是數(shù)據(jù)已經(jīng)成功持久化到數(shù)據(jù)庫(kù)中。在默認(rèn)情況下,dataSource 數(shù)據(jù)源的 autoCommit 被設(shè)置為 true 這也意謂著所有通過(guò) JdbcTemplate 執(zhí)行的語(yǔ)句馬上提交,沒(méi)有事務(wù)。如果將 dataSource 的 defaultAutoCommit 設(shè)置為 false,再次運(yùn)行 UserJdbcWithoutTransManagerService,將拋出錯(cuò)誤,原因是新增及更改數(shù)據(jù)的操作都沒(méi)有提交到數(shù)據(jù)庫(kù),所以 處的語(yǔ)句因無(wú)法從數(shù)據(jù)庫(kù)中查詢到匹配的記錄而引發(fā)異常。對(duì)于強(qiáng)調(diào)讀速度的應(yīng)用,數(shù)據(jù)庫(kù)本身可能就不支持事務(wù),如使用 MyISAM 引擎的 MySQL 數(shù)據(jù)庫(kù)。這時(shí),無(wú)須在 Spring 應(yīng)用中配置事務(wù)管理器,因?yàn)榧词古渲昧?,也是沒(méi)有實(shí)際用處的。不 過(guò),對(duì)于 Hibernate 來(lái)說(shuō),情況就有點(diǎn)復(fù)雜了。因?yàn)?Hibernate 的事務(wù)管理?yè)碛衅渥陨淼囊饬x,它和 Hibernate 一級(jí)緩存有密切的關(guān)系:當(dāng)我們調(diào)用 Session 的 save、update 等方法時(shí),Hibernate 并不直接向數(shù)據(jù)庫(kù)發(fā)送 SQL 語(yǔ)句,而是在提交事務(wù)(commit)或 flush 一級(jí)緩存時(shí)才真正向數(shù)據(jù)庫(kù)發(fā)送 SQL。所以,即使底層數(shù)據(jù)庫(kù)不支持事務(wù),Hibernate 的事務(wù)管理也是有一定好處的,不會(huì)對(duì)數(shù)據(jù)操作的效率造成負(fù)面影響。所以,如果是使用 Hibernate 數(shù)據(jù)訪問(wèn)技術(shù),沒(méi)有理由不配置 HibernateTransactionManager 事務(wù)管理器。但是,不使用 Hibernate 事務(wù)管理器,在 Spring 中,Hibernate 照樣也可以工作,來(lái)看下面的例子:清單 3.UserHibernateWithoutTransManagerService.java package user.withouttm;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Service;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.orm.hibernate3.HibernateTemplate;import mons.dbcp.BasicDataSource;import user.User;Service(service2)public class UserHibernateWithoutTransManagerService Autowired private HibernateTemplate hibernateTemplate; public void addScore(String userName,int toAdd) User user = (User)hibernateTemplate.get(User.class,userName); user.setScore(user.getScore()+toAdd); hibernateTemplate.update(user); public static void main(String args) /參考UserJdbcWithoutTransManagerService相應(yīng)代碼 此時(shí),采用 hiberWithoutTransManager.xml 的配置文件,其配置內(nèi)容如下:清單 4.hiberWithoutTransManager.xml user.User org.hibernate.dialect.Oracle10gDialect true 運(yùn) 行 UserHibernateWithoutTransManagerService,程序正確執(zhí)行,并得到類似于 UserJdbcWithoutTransManagerService 的執(zhí)行結(jié)果,這說(shuō)明 Hibernate 在 Spring 中,在沒(méi)有事務(wù)管理器的情況下,依然可以正常地進(jìn)行數(shù)據(jù)的訪問(wèn)?;仨?yè)首應(yīng)用分層的迷惑Web、 Service 及 DAO 三層劃分就像西方國(guó)家的立法、行政、司法三權(quán)分立一樣被奉為金科玉律,甚至有開(kāi)發(fā)人員認(rèn)為如果要使用 Spring 的事務(wù)管理就一定先要進(jìn)行三層的劃分。這個(gè)看似荒唐的論調(diào)在開(kāi)發(fā)人員中頗有市場(chǎng)。更有甚者,認(rèn)為每層必須先定義一個(gè)接口,然后再定義一個(gè)實(shí)現(xiàn)類。其結(jié)果 是:一個(gè)很簡(jiǎn)單的功能,也至少需要 3 個(gè)接口,3 個(gè)類,再加上視圖層的 JSP 和 JS 等,打牌都可以轉(zhuǎn)上兩桌了,這種誤解貽害不淺。對(duì) 將“面向接口編程”奉為圭臬,認(rèn)為放之四海而皆準(zhǔn)的論調(diào),筆者深不以為然。是的,“面向接口編程”是 Martin Fowler,Rod Johnson 這些大師提倡的行事原則。如果拿這條原則去開(kāi)發(fā)架構(gòu),開(kāi)發(fā)產(chǎn)品,怎么強(qiáng)調(diào)都不為過(guò)。但是,對(duì)于我們一般的開(kāi)發(fā)人員來(lái)說(shuō),做的最多的是普通工程項(xiàng)目,往往最 多的只是一些對(duì)數(shù)據(jù)庫(kù)增、刪、查、改的功能。此時(shí),“面向接口編程”除了帶來(lái)更多的類文件外,看不到更多其它的好處。Spring 框架提供的所有附加的好處(AOP、注解增強(qiáng)、注解 MVC 等)唯一的前提就是讓 POJO 的類變成一個(gè)受 Spring 容器管理的 Bean,除此以外沒(méi)有其它任何的要求。下面的實(shí)例用一個(gè) POJO 完成所有的功能,既是 Controller,又是 Service,還是 DAO:清單 5. MixLayerUserService.java package user.mixlayer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;/.將POJO類通過(guò)注解變成Spring MVC的ControllerControllerpublic class MixLayerUserService /.自動(dòng)注入JdbcTemplate Autowired private JdbcTemplate jdbcTemplate; /.通過(guò)Spring MVC注解映URL請(qǐng)求 RequestMapping(/logon.do) public String logon(String userName,String password) if(isRightUser(userName,password) String sql = UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?; jdbcTemplate.update(sql,20,userName); return success; else return fail; private boolean isRightUser(String userName,String password) /do sth. return true; 通 過(guò) Controller 注解將 MixLayerUserService 變成 Web 層的 Controller,同時(shí)也是 Service 層的服務(wù)類。此外,由于直接使用 JdbcTemplate 訪問(wèn)數(shù)據(jù),所以 MixLayerUserService 還是一個(gè) DAO。來(lái)看一下對(duì)應(yīng)的 Spring 配置文件:清單 6.applicationContext.xml 在 處,我們定義配置了 AnnotationMethodHandlerAdapter,以便啟用 Spring MVC 的注解驅(qū)動(dòng)功能。而和處通過(guò) Spring 的 aop 及 tx 命名空間,以及 Aspject 的切點(diǎn)表達(dá)式語(yǔ)法進(jìn)行事務(wù)增強(qiáng)的定義,對(duì) MixLayerUserService 的所有公有方法進(jìn)行事務(wù)增強(qiáng)。要使程序能夠運(yùn)行起來(lái)還必須進(jìn)行 web.xml 的相關(guān)配置:清單 7.web.xml contextConfigLocation classpath*:user/mixlayer/applicationContext.xml log4jConfigLocation /WEB-INF/classes/perties org.springframework.web.util.Log4jConfigListener org.springframework.web.context.ContextLoaderListener user org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:user/mixlayer/applicationContext.xml 1 user *.do 這 個(gè)配置文件很簡(jiǎn)單,唯一需要注意的是 DispatcherServlet 的配置。默認(rèn)情況下 Spring MVC 根據(jù) Servlet 的名字查找 WEB-INF 下的 -servlet.xml 作為 Spring MVC 的配置文件,在此,我們通過(guò) contextConfigLocation 參數(shù)顯式指定 Spring MVC 配置文件的確切位置。將 org.springframework.jdbc 及 org.springframework.transaction 的日志級(jí)別設(shè)置為 DEBUG,啟動(dòng)項(xiàng)目,并訪問(wèn) http:/localhost:8088/logon.do?userName=tom 應(yīng)用,MixLayerUserService#logon 方法將作出響應(yīng),查看后臺(tái)輸出日志:清單 8 執(zhí)行日志 13:24:22,625 DEBUG (AbstractPlatformTransactionManager.java:365) - Creating new transaction with name user.mixlayer.MixLayerUserService.logon: PROPAGATION_REQUIRED,ISOLATION_DEFAULT13:24:22,906 DEBUG (DataSourceTransactionManager.java:205) - Acquired Connection mons.dbcp.PoolableConnection6e1cbf for JDBC transaction13:24:22,921 DEBUG (DataSourceTransactionManager.java:222) - Switching JDBC Connection mons.dbcp.PoolableConnection6e1cbf to manual commit13:24:22,921 DEBUG (JdbcTemplate.java:785) - Executing prepared SQL update13:24:22,921 DEBUG (JdbcTemplate.java:569) - Executing prepared SQL statement UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?13:24:23,140 DEBUG (JdbcTemplate.java:794) - SQL update affected 0 rows13:24:23,140 DEBUG (AbstractPlatformTransactionManager.java:752) - Initiating transaction commit13:24:23,140 DEBUG (DataSourceTransactionManager.java:265) - Committing JDBC transaction on Connection mons.dbcp.PoolableConnection6e1cbf13:24:23,140 DEBUG (DataSourceTransactionManager.java:323) - Releasing JDBC Connection mons.dbcp.PoolableConnection6e1cbf after transaction13:24:23,156 DEBUG (DataSourceUtils.java:312) - Returning JDBC Connection to DataSource日志中粗體部分說(shuō)明了 MixLayerUserService#logon 方法已經(jīng)正確運(yùn)行在事務(wù)上下文中。Spring 框架本身不應(yīng)該是復(fù)雜化代碼的理由,使用 Spring 的開(kāi)發(fā)者應(yīng)該是無(wú)拘無(wú)束的:從實(shí)際應(yīng)用出發(fā),去除掉那些所謂原則性的接口,去除掉強(qiáng)制分層的束縛,簡(jiǎn)單才是硬道理。事務(wù)方法嵌套調(diào)用的迷茫Spring 事務(wù)一個(gè)被訛傳很廣說(shuō)法是:一個(gè)事務(wù)方法不應(yīng)該調(diào)用另一個(gè)事務(wù)方法,否則將產(chǎn)生兩個(gè)事務(wù)。結(jié)果造成開(kāi)發(fā)人員在設(shè)計(jì)事務(wù)方法時(shí)束手束腳,生怕一不小心就踩到地雷。其實(shí)這種是不認(rèn)識(shí) Spring 事務(wù)傳播機(jī)制而造成的誤解,Spring 對(duì)事務(wù)控制的支持統(tǒng)一在 TransactionDefinition 類中描述,該類有以下幾個(gè)重要的接口方法:int getPropagationBehavior():事務(wù)的傳播行為int getIsolationLevel():事務(wù)的隔離級(jí)別int getTimeout():事務(wù)的過(guò)期時(shí)間boolean isReadOnly():事務(wù)的讀寫(xiě)特性。很 明顯,除了事務(wù)的傳播行為外,事務(wù)的其它特性 Spring 是借助底層資源的功能來(lái)完成的,Spring 無(wú)非只充當(dāng)個(gè)代理的角色。但是事務(wù)的傳播行為卻是 Spring 憑借自身的框架提供的功能,是 Spring 提供給開(kāi)發(fā)者最珍貴的禮物,訛傳的說(shuō)法玷污了 Spring 事務(wù)框架最美麗的光環(huán)。所謂事務(wù)傳播行為就是多個(gè)事務(wù)方法相互調(diào)用時(shí),事務(wù)如何在這些方法間傳播。Spring 支持 7 種事務(wù)傳播行為:PROPAGATION_REQUIRED 如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù),如果已經(jīng)存在一個(gè)事務(wù)中,加入到這個(gè)事務(wù)中。這是最常見(jiàn)的選擇。PROPAGATION_SUPPORTS 支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式執(zhí)行。PROPAGATION_MANDATORY 使用當(dāng)前的事務(wù),如果當(dāng)前沒(méi)有事務(wù),就拋出異常。PROPAGATION_REQUIRES_NEW 新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。PROPAGATION_NOT_SUPPORTED 以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。PROPAGATION_NEVER 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。PROPAGATION_NESTED 如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒(méi)有事務(wù),則執(zhí)行與 PROPAGATION_REQUIRED 類似的操作。Spring 默認(rèn)的事務(wù)傳播行為是 PROPAGATION_REQUIRED,它適合于絕大多數(shù)的情況。假設(shè) ServiveX#methodX() 都工作在事務(wù)環(huán)境下(即都被 Spring 事務(wù)增強(qiáng)了),假設(shè)程序中存在如下的調(diào)用 鏈:Service1#method1()-Service2#method2()-Service3#method3(),那么這 3 個(gè)服務(wù)類的 3 個(gè)方法通過(guò) Spring 的事務(wù)傳播機(jī)制都工作在同一個(gè)事務(wù)中。下面,我們來(lái)看一下實(shí) 例,UserService#logon() 方法內(nèi)部調(diào)用了 UserService#updateLastLogonTime() 和 ScoreService#addScore() 方法,這兩個(gè)類都繼承于 BaseService。它們之間的類結(jié)構(gòu)說(shuō)明如下:圖 1. UserService 和 ScoreService具體的代碼如下所示:清單 9 UserService.java Service(userService)public class UserService extends BaseService Autowired private JdbcTemplate jdbcTemplate; Autowired private ScoreService scoreService; public void logon(String userName) updateLastLogonTime(userName); scoreService.addScore(userName, 20); public void updateLastLogonTime(String userName) String sql = UPDATE t_user u SET u.last_logon_time = ? WHERE user_name =?; jdbcTemplate.update(sql, System.currentTimeMillis(), userName); UserService 中注入了 ScoreService 的 Bean,ScoreService 的代碼如下所示:清單 10 ScoreService.java Service(scoreUserService)public class ScoreService extends BaseService Autowired private JdbcTemplate jdbcTemplate; public void addScore(String userName, int toAdd) String sql = UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?; jdbcTemplate.update(sql, toAdd, userName); 通過(guò) Spring 的事務(wù)配置為 ScoreService 及 UserService 中所有公有方法都添加事務(wù)增強(qiáng),讓這些方法都工作于事務(wù)環(huán)境下。下面是關(guān)鍵的配置代碼:清單 11 事務(wù)增強(qiáng)配置 aop:pointcut id=serviceJdbcMethod expression=within(user.nestcall.BaseService+)/ 將日志級(jí)別設(shè)置為 DEBUG,啟動(dòng) Spring 容器并執(zhí)行 UserService#logon() 的方法,仔細(xì)觀察如下的輸出日志:清單 12 執(zhí)行日志 16:25:04,765 DEBUG (AbstractPlatformTransactionManager.java:365) - Creating new transaction with name user.nestcall.UserService.logon: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 為UserService#logon方法啟動(dòng)一個(gè)事務(wù)16:25:04,765 DEBUG (DataSourceTransactionManager.java:205) - Acquired Connection mons.dbcp.PoolableConnection32bd65 for JDBC transactionlogon method.updateLastLogonTime. 直接執(zhí)行updateLastLogonTime方法16:25:04,781 DEBUG (JdbcTemplate.ja
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 公司臘八活動(dòng)策劃方案
- 2025年藝術(shù)設(shè)計(jì)專業(yè)技能考試試題及答案
- 2025年物流管理專業(yè)考試試卷及答案
- 2025年市場(chǎng)營(yíng)銷師職業(yè)考試試題及答案
- 多傳感器融合定位-第4篇-洞察及研究
- 2025年青少年犯罪預(yù)防與干預(yù)知識(shí)考試試卷及答案
- 2025年機(jī)器人技術(shù)應(yīng)用職業(yè)資格考試題及答案
- 2025年基礎(chǔ)音樂(lè)教育與技能考試試卷及答案
- 2025年短視頻制作與傳播課程考試試題及答案
- 2025年中國(guó)立袋行業(yè)市場(chǎng)全景分析及前景機(jī)遇研判報(bào)告
- 外科病應(yīng)急預(yù)案嵌頓疝病人應(yīng)急預(yù)案
- JJF 1069-2012 法定計(jì)量檢定機(jī)構(gòu)考核規(guī)范(培訓(xùn)講稿)
- 加油站有限空間安全警示牌
- 安全員的任職條件及職責(zé)
- 資產(chǎn)評(píng)估收費(fèi)管理辦法(2023)2914
- 出師表標(biāo)準(zhǔn)注音版修正版
- 孤獨(dú)癥康復(fù)教育人員上崗培訓(xùn)練習(xí)題庫(kù)及答案
- 籃球比賽記錄表A4版
- 機(jī)械設(shè)備投入計(jì)劃及保證措施
- 小兒清熱止咳口服液產(chǎn)品知識(shí)-課件
- 鋼 筋 檢 查 記 錄 表(鋼筋加工及安裝)
評(píng)論
0/150
提交評(píng)論