日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实战SSM_O2O商铺_10【商铺注册】Service层的实现

發布時間:2025/3/21 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实战SSM_O2O商铺_10【商铺注册】Service层的实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 概述
  • ShopService開發步驟
    • Service層接口類ShopService
    • Service層接口實現類ShopServiceImpl
    • ShopOperationException
    • 單元測試
  • 注意事項
  • Github地址

概述

截至目前,我們已經完成了持久層insertShop的開發,編寫了操作圖片和路徑的工具類,使用ENUM定義了操作店鋪使用的常量,定義了操作店鋪返回的DTO類ShopExecution。

鋪墊了這么多,終于可以編寫Service層的代碼了,service層操作店鋪返回DTO類ShopExecution(不僅包含Shop的信息,同時也要包含操作店鋪的狀態信息)。


ShopService開發步驟


Service層接口類ShopService

src/main/java建立 com.artisan.o2o.service包,新增接口類ShopService

package com.artisan.o2o.service;import java.io.File;import com.artisan.o2o.dto.ShopExecution; import com.artisan.o2o.entity.Shop;public interface ShopService {ShopExecution addShop(Shop shop, File shopFile);}

Service層接口實現類ShopServiceImpl

src/main/java先建立com.artisan.o2o.service.impl, 編寫ShopService的接口實現類ShopServiceImpl

具體邏輯詳見注釋

package com.artisan.o2o.service.impl;import java.io.File; import java.util.Date;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;import com.artisan.o2o.dao.ShopDao; import com.artisan.o2o.dto.ShopExecution; import com.artisan.o2o.entity.Shop; import com.artisan.o2o.enums.ShopStateEnum; import com.artisan.o2o.exception.ShopOperationException; import com.artisan.o2o.service.ShopService; import com.artisan.o2o.util.FileUtil; import com.artisan.o2o.util.ImageUtil;@Service public class ShopServiceImpl implements ShopService {private static final Logger logger = LoggerFactory.getLogger(ShopServiceImpl.class);@Autowiredprivate ShopDao shopDao;/*** 3個步驟需要在一個事務中,添加@Transactional注解* * 1. 將shop基本信息添加到數據庫,返回shopId* * 2. 根據shopId創建目錄,得到圖片存儲的相對路徑* * 3. 將相對路徑更新到數據庫* * * Spring默認情況下會對運行期例外(RunTimeException)進行事務回滾* * (1)注解@Transactional 只能應用到 public 方法才有效* * (2)在 Spring 的 AOP 代理下,只有目標方法由外部調用,目標方法才由 Spring成的代理對象來管理,這會造成自調用問題。* 若同一類中的其他沒有@Transactional 注解的方法內部調用有@Transactional 注解的方法,* 有@Transactional注解的方法的事務被忽略,不會發生回滾。* * * 上面的兩個問題@Transactional 注解只應用到 public 方法和自調用問題,是由于使用 Spring AOP* 代理造成的。為解決這兩個問題,可以使用 AspectJ 取代 Spring AOP 代理* * 在應用系統調用聲明@Transactional 的目標方法時,Spring Framework 默認使用 AOP* 代理,在代碼運行時生成一個代理對象,根據@Transactional 的屬性配置信息,這個代理對象決定該聲明@Transactional* 的目標方法是否由攔截器 TransactionInterceptor 來使用攔截,在 TransactionInterceptor* 攔截時,會在在目標方法開始執行之前創建并加入事務,并執行目標方法的邏輯,* 最后根據執行情況是否出現異常,利用抽象事務管理器AbstractPlatformTransactionManager 操作數據源* DataSource 提交或回滾事務* */@Override@Transactionalpublic ShopExecution addShop(Shop shop, File shopImg) {// 非空判斷 (這里先判斷shop是否為空,嚴格意義上講shop中的are的屬性也需要判斷)if (shop == null) {return new ShopExecution(ShopStateEnum.NULL_SHOP_INFO);}// 關鍵步驟1. 設置基本信息,插入shop// 初始狀態: 審核中shop.setEnableStatus(0);shop.setCreateTime(new Date());shop.setLastEditTime(new Date());int effectedNum = shopDao.insertShop(shop);if (effectedNum <= 0) {throw new ShopOperationException("店鋪創建失敗");} else {// 關鍵步驟2. 添加成功,則繼續處理文件,獲取shopid,用于創建圖片存放的目錄if (shopImg != null) {try {// 需要根據shopId來創建目錄,所以也需要shop這個入參addShopImg(shop, shopImg);} catch (Exception e) {logger.error("addShopImg error {} ", e.toString());throw new ShopOperationException("addShopImg error:" + e.getMessage());}// 關鍵步驟3. 更新tb_shop中 shop_img字段effectedNum = shopDao.updateShop(shop);if (effectedNum <= 0) {logger.error("updateShop error {} ", "更新店鋪失敗");throw new ShopOperationException("updateShop error");}}}// 返回店鋪的狀態:審核中,以及店鋪信息return new ShopExecution(ShopStateEnum.CHECK, shop);}/*** * * @Title: addShopImg* * @Description: 根據shopId創建目錄,并生成水印圖片* * @param shop* @param shopImg* * @return: void*/private void addShopImg(Shop shop, File shopImg) {String imgPath = FileUtil.getShopImagePath(shop.getShopId());// 生成圖片的水印圖String relativeAddr = ImageUtil.generateThumbnails(shopImg, imgPath);// 將相對路徑設置個shop,用于更新數據庫shop.setShopImg(relativeAddr);}}

ShopOperationException

package com.artisan.o2o.exception;/*** * * @ClassName: ShopOperationException* * @Description: 繼承自RuntimeException ,這樣在標注了@Transactional事務的方法中,出現了異常,才回回滾數據。* * 默認情況下,如果在事務中拋出了未檢查異常(繼承自 RuntimeException 的異常)或者 Error,則 Spring* 將回滾事務;除此之外,Spring 不會回滾事務。* * @author: Mr.Yang* * @date: 2018年5月21日 下午5:37:53*/ public class ShopOperationException extends RuntimeException {private static final long serialVersionUID = 6860566652051914211L;public ShopOperationException(String message) {super(message);}}

單元測試

package com.artisan.o2o.service;import java.io.File; import java.util.Date;import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired;import com.artisan.o2o.BaseTest; import com.artisan.o2o.dto.ShopExecution; import com.artisan.o2o.entity.Area; import com.artisan.o2o.entity.PersonInfo; import com.artisan.o2o.entity.Shop; import com.artisan.o2o.entity.ShopCategory; import com.artisan.o2o.enums.ShopStateEnum;public class ShopServiceTest extends BaseTest {@AutowiredShopService shopService;@Testpublic void testAddShop() {Shop shop = new Shop();PersonInfo personInfo = new PersonInfo();Area area = new Area();ShopCategory shopCategory = new ShopCategory();personInfo.setUserId(1L);area.setAreaId(1);shopCategory.setShopCategoryId(1L);shop.setOwner(personInfo);shop.setArea(area);shop.setShopCategory(shopCategory);shop.setShopName("咖啡點");shop.setShopDesc("小工匠的咖啡店");shop.setShopAddr("NanJing");shop.setPhone("9876553");shop.setPriority(99);shop.setCreateTime(new Date());shop.setLastEditTime(new Date());shop.setEnableStatus(ShopStateEnum.CHECK.getState());shop.setAdvice("審核中");File shopFile = new File("D:/o2o/artisan.jpg");ShopExecution se = shopService.addShop(shop, shopFile);Assert.assertEquals(ShopStateEnum.CHECK.getState(), se.getState());} }

可以在addShop方法中,加入斷點,通過debug的方式,一步步的調試分析

mybatis操作數據庫的信息:

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter. 五月 21, 2018 6:09:55 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager 信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 2, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 10000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1br1ebw9v10u0o3ghf6lww|130d63be, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1br1ebw9v10u0o3ghf6lww|130d63be, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/o2o?useUnicode=true&characterEncoding=utf8, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 30, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 10, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ] Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@512baff6] JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@3adcc812] will be managed by Spring ==> Preparing: INSERT INTO tb_shop ( owner_id, area_id, shop_category_id, shop_name, shop_desc, shop_addr, phone, shop_img, priority, create_time, last_edit_time, enable_status, advice) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ); ==> Parameters: 1(Long), 1(Integer), 1(Long), 咖啡點(String), 小工匠的咖啡店(String), NanJing(String), 9876553(String), null, 99(Integer), 2018-05-21 18:09:57.067(Timestamp), 2018-05-21 18:09:57.067(Timestamp), 0(Integer), 審核中(String) <== Updates: 1 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@512baff6] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@512baff6] from current transaction ==> Preparing: update tb_shop SET shop_name=?, shop_desc=?, shop_addr=?, phone=?, shop_img=?, priority=?, last_edit_time=?, enable_status=?, advice=?, area_id=?, shop_category_id=? where shop_id = ? ==> Parameters: 咖啡點(String), 小工匠的咖啡店(String), NanJing(String), 9876553(String), \upload\item\shopImage\24\2018052118095757182.jpg(String), 99(Integer), 2018-05-21 18:09:57.067(Timestamp), 0(Integer), 審核中(String), 1(Integer), 1(Long), 24(Long) <== Updates: 1 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@512baff6] Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@512baff6] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@512baff6] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@512baff6] 五月 21, 2018 6:09:58 下午 org.springframework.context.support.GenericApplicationContext doClose 信息: Closing org.springframework.context.support.GenericApplicationContext@ae45eb6: startup date [Mon May 21 18:09:50 BOT 2018]; root of context hierarchy

數據庫信息:

同樣的需要檢查下操作水印圖片的操作是否正常,加上了水印,OK


注意事項

1. addShop的多個操作步驟(設置基本信息,插入tb_shop || 添加成功,則繼續處理文件,獲取shopid,用于創建圖片存放的目錄 || 更新tb_shop中 shop_img字段 ),需要找同一個事務中,所以addShop方法添加了@Transactional注解

2. Spring默認情況下會對運行期例外(RunTimeException)進行事務回滾,所以ShopOperationException必須繼承RuntimeException才可以實現回滾,如果繼承Exception則不會回滾數據庫操作。


Github地址

代碼地址: https://github.com/yangshangwei/o2o

總結

以上是生活随笔為你收集整理的实战SSM_O2O商铺_10【商铺注册】Service层的实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。