精华内容
下载资源
问答
  • 现在需要开发四张报表,四张报表的数据都储存在一张数据表当中。其中这张表的字段有一个TIME_PERD_ID字段来记录日期 日期格式为:20130101,......,20130131 四张报表中有两个月报表,两个周报表。现在需要开发一...
  • 很惭愧,做了两年的软件开发,那些业务逻辑该放在业务逻辑层,哪些业务逻辑该用存储过程来实现,心里一直是一团浆糊。从大学开始,我就对SQL语句有着说不出的讨厌,所以我对数据库技术知之甚少,所以要实现某个功能...
       很惭愧,做了两年的软件开发,那些业务逻辑该放在业务逻辑层,哪些业务逻辑该用存储过程来实现,心里一直是一团浆糊。从大学开始,我就对SQL语句有着说不出的讨厌,所以我对数据库技术知之甚少,所以要实现某个功能,首先想到的就是抽象业务流程,设计接口,抽象类型,提取核心流程做基础设计,最后才考虑数据的存储,所以我建表几乎是从来不考虑满足那个什么三范式的。类型到数据表的相互映射,也是中规中矩的自己造轮子,利用特性、反射,从不用成熟的ORM框架。

         因为做的项目较小,数据处理也不是很多,所以上述做法也行得通,而且自我感觉良好。但是我最近仔细思考了我做过的项目,几乎所有的业务都是对数据的处理,归根结底还是对数据的枚举和对数据的修改。数据库的存储工作不是能以最好的性能满足对数据的枚举和对数据的修改么?而且存储过程的优点很多:

    • 减少网络带宽,按理论存储过程会提高性能.
    • 无需重新编译,更改后即可运行,无需重新编译代码
    • 由专门的dba写的sql语句更高效
    • 安全性(在传输用户名密码时,可防止注入等情况)

         后来的几个项目我又改变了风格,纯粹用存储过程来开发,中间的业务逻辑层几乎纯粹成了数据传递层,完全抛弃了模型类和场景类,从前端到后台都是DataTable过来过去,中间用了微软的强类型表。项目也照样完成得很好,而且速度奇快。当然,存储过程也有他的缺点:

    • 依赖于数据库厂商,难以移植(当一个小系统发展到大系统时,对数据库的要求也会发生改变)
    • 业务逻辑大的时候,封装性不够,难调试难以维护
    • 复杂的应用用存储过程来实现,就把业务处理的负担压在数据库服务器上了。没有办法通过中间层来灵活分担负载和压力.均衡负载等

          但我们又有多少项目需要移植数据库呢,又有多少业务逻辑是存储过程解决不了呢,又有多少项目是让数据库系统满负荷运行呢?可能我是菜鸟,但我做的几十个项目中,真的极少遇到上述的情况。

          两厢对比,迷糊了,晕菜了,我潜意识里知道存储过程实现所有的业务是不好的,而且存储过程的IDE没有“重构”“查找所有引用”这样贴心的小功能,维护确实很恼火。但我又说不出这东西究竟差在那些大地方,求园子里面的达人指点指点呀,你们的业务逻辑是如何在业务逻辑层实现的呀,求解惑……

          最后,帮公司发个招聘启示:

          成都九洲电子信息是一家有军工背景的企业,在物联网、 RFID方面有核心竞争力,现在因为项目需要,大量招聘 .Net开发人员,月薪4000-8000。详情请见:

    http://job.cnblogs.com/offer/13828/

    转载于:https://www.cnblogs.com/kangyifei/archive/2011/07/27/2119001.html

    展开全文
  • 说明这里举一个非常简单的例子,以案例的业务实现来分析如何写好业务代码。本案例只是简单的模拟,可能与真实的情况有出入,这里只是为了举例使用。案例:用户挑选商品放入购物车,然后下单结算,流程如下:挑选商品...

    0db84c51778069e2e678e6cfca632689.gif

    说明

    这里举一个非常简单的例子,以案例的业务实现来分析如何写好业务代码。

    本案例只是简单的模拟,可能与真实的情况有出入,这里只是为了举例使用。

    案例:

    用户挑选商品放入购物车,然后下单结算,流程如下:

    1. 挑选商品

    2. 下单

    3. 结算

    4. 生成订单

    5. 通知

    提交下单的业务逻辑如下:

    1. 验证账号是否合法

    2. 调用第三方接口查看商品的打折价格

    3. 钱包金额扣除

    4. 生成订单信息

    5. 通知用户下单成功,等待收货

    代码实现

    @Service
    public class OrderServiceImpl implements OrderService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private KafkaTemplate kafkaTemplate;

    /**
    * 购买商品,提交订单
    * @param userId 用户ID
    * @param productId 商品ID
    * @return
    */

    public Result submit(Long userId, Long productId) throws BizException {
    // 验证账号
    UserDO userDO = userMapper.findById(userId);
    if (userDO == null) {
    throw BizException(USER_NOT_EXISTS);
    }
    // 查看商品信息及打折信息
    ProductDO productDO = productMapper.findById(productId);
    Double delta = HttpUtils.getDiscount(productId);
    double actualPayment = productDO.getPrice() - delta;
    Money money = userDO.getMoney();
    if (actualPayment > money.getRemain()) {
    // 如果商品价格 - 优惠价格 > 用户钱包,则说明不够付
    return Result.fail("余额不足");
    }
    // 钱包够付,扣除金额
    double remain = money.getRemain() - actualPayment;
    money.setRemain(remain);
    // 更新账号钱包余额
    userMapper.update(userDO);
    // 生成订单信息
    OrderDO orderDO = new OrderDO();
    orderDO.setUserId(userId);
    orderDO.setProductId(productId);
    orderMapper.save(orderDO);
    // 通知用户订单已生成,等待收货
    kafkaTemplate.send("orderTopic", orderDO);
    return Result.ok();
    }
    }

    上面代码写好了,而且可以实现相关功能,但是随着业务的迭代,可能会出现很多问题:

    1. 可维护性差:

    • XxMapper是基于Mybatis实现数据操作层,也就把技术细节带入业务逻辑中了,如果技术实现变了(改为使用Hibernate,或Mybatis版本升级造成用法改变等),业务代码就得改变。

    • XxDO 是和数据表绑定的,数据表结构变更等也会影响业务代码。

    • 调用第三方API,直接在业务代码中调用HttpUtils完成,未来第三方API修改了方法签名或返回值,或改为了RPC接口,那么业务代码也会随着改变。

    • 发送消息直接使用KafkaTemplate,如果技术选型变了要改为使用RocketMQ,那么业务代码还得变。

    1. 可扩展性差:

    • 如果商品因为做活动又加了其他的优惠,或商品某一段时间不打折了,那么原有的代码就会重新改来改去;

    • 业务逻辑和数据存储结构是依赖的,数据存储结构的变化对业务的影响可想而知;

    1. 可测试性差:

    • 因为直接依赖了数据库,第三方接口,中间件,所以需要所有技术实现后才能进行测试,测试成本和时间都比较大。

    代码优化一

    我们上面说了,数据库操作不应该直接暴露在业务逻辑中,因此把数据库操作“隔离”开

    public interface UserRepository {

    User findById(Long userId);
    }

    新增XxRepository接口,业务逻辑直接依赖接口/抽象,而不应该直接依赖实现。

    Repository是数据仓库,不一定非得是DB,也可以是其他的数据操作。

    Repository返回的对象也不是DO,与数据库结构无关。

    代码优化二

    DO对象是只有 set, get操作,没有其他行为,我们说这有时是一种贫血现象,会导致本该在业务领域实体中完成的事情散落到各个Service中,低内聚而且也不好维护。

    增加领域实体,相关行为直接在实体内完成(高内聚):

    public class Money {

    private double remain;

    public double getRemain() {
    return remain;
    }

    public void setRemain(double remain) {
    this.remain = remain;
    }

    /**
    * 扣费
    * @param delta
    * @return
    */

    public boolean charge(double delta) {
    if (remain < delta) {
    return false;
    }
    this.remain -= delta;
    return true;
    }
    }

    代码优化三

    第三方接口是不可靠的,方法签名或返回值或调用方式都有可能会变的,如果直接在业务中依赖,会对业务造成“腐蚀”,所以应该加一层适配层(也叫防腐层ACL)。

    /**
    * 防腐层/适配层
    */

    @Service
    public class PayServiceImpl implements PayService {

    @Autowired
    private DiscountFacade discountFacade;

    /**
    * 支付
    * @param money
    * @param product
    * @return
    */

    public boolean pay(Money money, Product product) {
    // 获取优惠
    Double delta = discountFacade.getDiscount(product.getId());
    // 扣除费用
    return money.charge(product.getPrice() - delta);
    }
    }

    代码优化四

    抽象中间件,不直接依赖具体的MQ实现

    public interface MessageProducer<T, R> {

    Resultsend(T message);
    }

    总结

    优化后的代码如下:

        @Autowired
    private UserRepository userRepository;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private MessageProducer messageProducer;@Autowiredprivate PayService payService;/**
    * 购买商品,提交订单
    * @param userId 用户ID
    * @param productId 商品ID
    * @return
    */
    public Result submit(Long userId, Long productId) throws BizException {// 验证
    User user = userRepository.findByUserId(userId);if (user == null) {throw BizException(USER_NOT_EXISTS);
    }// 支付
    Product product = productRepository.findById(productId);
    boolean f = payService.pay(user.getMoney(), product);if (!f) {return Result.fail("费用扣除失败");
    }// 更新账户
    userRepository.update(user);// 生成订单信息
    Order order = OrderFactory.create(user, product);
    orderRepository.add(order);// 通知用户订单已生成,等待收货
    messageProducer.send(order);return Result.ok();
    }

    代码不一定非常严谨,只是通过这一个简单的例子告诉大家实际工作中代码该怎么写,该遵循哪些目标:

    • 独立于框架:架构不应该依赖某个外部的库或框架,不应该被框架的结构所束缚。

    • 独立于UI:前台展示的样式可能会随时发生变化(今天可能是网页、明天可能变成console、后天是独立app),但是底层架构不应该随之而变化。

    • 独立于底层数据源:无论今天你用MySQL、Oracle还是MongoDB、CouchDB,甚至使用文件系统,软件架构不应该因为不同的底层数据储存方式而产生巨大改变。

    • 独立于外部依赖:无论外部依赖如何变更、升级,业务的核心逻辑不应该随之而大幅变化。

    • 可测试:无论外部依赖了什么数据库、硬件、UI或者服务,业务的逻辑应该都能够快速被验证正确性。

    来源:

    https://www.toutiao.com/i6903053083555807752/

    “IT大咖说”欢迎广大技术人员投稿,投稿邮箱:aliang@itdks.com

    30cdcb7dd1d4f9b20afe38b90d74f224.gif来都来了,走啥走,留个言呗~

     IT大咖说  |  关于版权 

    由“IT大咖说(ID:itdakashuo)”原创的文章,转载时请注明作者、出处及微信公众号。投稿、约稿、转载请加微信:ITDKS10(备注:投稿),茉莉小姐姐会及时与您联系!

    感谢您对IT大咖说的热心支持!

    相关推荐

    推荐文章

    • 高效交付的秘诀,开源 DevOps 运维平台合集

    • 海量订单系统微服务开发:使用MongoDB支持海量数据

    • 微服务网关——设计篇

    • 一个开源的密码管理器

    • 基于 Ant Design Vue 的 Vue3.0 框架

    • MaxCompute 自适应执行引擎DAG 2.0为1.5亿分布式作业提供自动化保障

    展开全文
  • 问问大家把业务代码用数据库实现(包括触发器,储存过程这些)会不会更好一些
  • 如果储存在数据库(只读的表),那么每一个业务都需要查询一张或多张这样的静态数据表。 如果直接以关联数组的形式储存在PHP业务层(当然是从EXCEL策划表架构自动产生的PHP代码),那么对庞大的关联数组进行定义、...
  • 储存过程

    2017-10-21 15:15:00
    这是一种pl sql语言,可以理解为在sql中做业务逻辑判断,,当然这回降低数据库的性能。 使用%type,可以声明的变量类型与某一张表的字段类型一样 变量的声明,有两种,table(数组)、record(类) 使用%...

    这里以oracle为例

    这是一种pl sql语言,可以理解为在sql中做业务逻辑判断,,当然这回降低数据库的性能。

    134920_9XUZ_3546063.png

     

    使用%type,可以声明的变量类型与某一张表的字段类型一样

    141308_FZrT_3546063.png

     

    变量的声明,有两种,table(数组)、record(类)

    141054_YkAU_3546063.png

    使用%rowtype让声明的变量跟着数据库表的变化而变化

    142429_HDTM_3546063.png

     

    insert 语句要有into 意思是把查出来的数据放在定义的变量中,所以就必须返回一条记录,多和没有都报错

    143306_pNdw_3546063.png

     

    sql%rowcount  统计执行的sql影响了多少行数据

    144037_mVgw_3546063.png

     

    条件判断

    145252_4Ha6_3546063.png

     

    带参数的存储过程  in (传入) out(传出) 默认(传入) in out (既传入又传出)

    先创建存储过程,在创建时报错需要show errors ,即使创建时有语法错误,也会被创建,,后执行

    183841_fwYu_3546063.png

    184811_3GAh_3546063.png

     

    转载于:https://my.oschina.net/u/3546063/blog/1554314

    展开全文
  • 我们大家都知道MySQL存储过程是从 MySQL 5.0 开始逐渐增加新的功能。存储过程在实际应用中也是优点大于缺点。不过最主要的还是执行效率和SQL 代码封装。特别是 SQL 代码封装功能,...现在有了 MySQL 存储过程,业务...

    我们大家都知道MySQL存储过程是从 MySQL 5.0 开始逐渐增加新的功能。存储过程在实际应用中也是优点大于缺点。不过最主要的还是执行效率和SQL 代码封装。特别是 SQL 代码封装功能,如果没有存储过程。

    在外部程序访问数据库时(例如 PHP),要组织很多 SQL 语句。

    特别是业务逻辑复杂的时候,一大堆的 SQL 和条件夹杂在 PHP 代码中,让人不寒而栗。现在有了 MySQL 存储过程,业务逻辑可以封装存储过程中,这样不仅容易维护,而且执行效率也高。

    实例一:无参的存储过程

    $conn = mysql_connect(‘localhost’,’root’,’root’) or die (“数据连接错误!!!”);

    mysql_select_db(‘test’,$conn);

    $sql = ”

    create procedure myproce()

    begin

    INSERT INTO user (id, username, sex) VALUES (NULL, ‘s’, ‘0’);

    end;

    “;

    mysql_query($sql);//创建一个myproce的存储过程

    $sql = “call test.myproce();”;

    mysql_query($sql);//调用myproce的存储过程,则数据库中将增加一条新记录。

    实例二:传入参数的存储过程

    $sql = ”

    create procedure myproce2(in score int)

    begin

    if score >= 60 then

    select ‘pass’;

    else

    select ‘no’;

    end if;

    end;

    “;

    mysql_query($sql);//创建一个myproce2的存储过程

    $sql = “call test.myproce2(70);”;

    mysql_query($sql);//调用myproce2的存储过程,看不到效果,可以在cmd下看到结果。

    实例三:传出参数的存储过程

    $sql = ”

    create procedure myproce3(out score int)

    begin

    set score=100;

    end;

    “;

    mysql_query($sql);//创建一个myproce3的存储过程

    $sql = “call test.myproce3(@score);”;

    mysql_query($sql);//调用myproce3的存储过程

    $result = mysql_query(‘select @score ;’);

    $array = mysql_fetch_array($result);

    echo ‘

    ’;print_r($array);

    实例四:传出参数的inout存储过程

    $sql = ”

    create procedure myproce4(inout sexflag int)

    begin

    SELECT * FROM user WHERE sex = sexflag;

    end;

    “;

    mysql_query($sql);//创建一个myproce4的存储过程

    $sql = “set @sexflag = 1”;

    mysql_query($sql);//设置性别参数为1

    $sql = “call test.myproce4(@sexflag);”;

    mysql_query($sql);//调用myproce4的存储过程,在cmd下面看效果

    实例五:使用变量的存储过程

    $sql = ”

    create procedure myproce5(in a int,in b int)

    begin

    declare s int default 0;

    set s=a+b;

    select s;

    end;

    “;

    mysql_query($sql);//创建一个myproce5的存储过程

    $sql = “call test.myproce5(4,6);”;

    mysql_query($sql);//调用myproce5的存储过程,在cmd下面看效果

    实例六:case语法

    $sql = ”

    create procedure myproce6(in score int)

    begin

    case score

    when 60 then select ‘及格’;

    when 80 then select ‘及良好’;

    when 100 then select ‘优秀’;

    else select ‘未知分数’;

    end case;

    end;

    “;

    mysql_query($sql);//创建一个myproce6的存储过程

    $sql = “call test.myproce6(100);”;

    mysql_query($sql);//调用myproce6的存储过程,在cmd下面看效果

    实例七:循环语句

    $sql = ”

    create procedure myproce7()

    begin

    declare i int default 0;

    declare j int default 0;

    while i<10 do

    set j=j+i;

    set i=i+1;

    end while;

    select j;

    end;

    “;

    mysql_query($sql);//创建一个myproce7的存储过程

    $sql = “call test.myproce7();”;

    mysql_query($sql);//调用myproce7的存储过程,在cmd下面看效果

    实例八:repeat语句

    $sql = ”

    create procedure myproce8()

    begin

    declare i int default 0;

    declare j int default 0;

    repeat

    set j=j+i;

    set i=i+1;

    until j>=10

    end repeat;

    select j;

    end;

    “;

    mysql_query($sql);//创建一个myproce8的存储过程

    $sql = “call test.myproce8();”;

    mysql_query($sql);//调用myproce8的存储过程,在cmd下面看效果

    实例九:loop语句

    $sql = ”

    create procedure myproce9()

    begin

    declare i int default 0;

    declare s int default 0;

    loop_label:loop

    set s=s+i;

    set i=i+1;

    if i>=5 then

    leave loop_label;

    end if;

    end loop;

    select s;

    end;

    “;

    mysql_query($sql);//创建一个myproce9的存储过程

    $sql = “call test.myproce9();”;

    mysql_query($sql);//调用myproce9的存储过程,在cmd下面看效果

    实例十:删除存储过程

    mysql_query(“drop procedure if exists myproce”);//删除test的存储过程

    展开全文
  • mysql储存过程

    2017-07-25 22:49:34
    功能:使用sql语句实现复杂的业务逻辑 Demo: 例1 create procedure p1() //p1:过程的名字;():必须有 不能加 ; 分号表示结束(什么都不要加) begin insert into users (account ,pwd) values ('zzc','...
  • 我们大家都知道MySQL存储过程是从 MySQL 5.0 开始逐渐增加新的功能。存储过程在实际应用中也是优点大于缺点。不过最主要的还是执行效率和SQL 代码封装。特别是 SQL 代码封装功能,...现在有了 MySQL 存储过程,业务...
  • 1,"count":1}],"search_count":[{"count_phone":6,"count":6}]},"card":[{"des":"云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。...
  • SpringBoot JPA 调用SQLServer储存过程

    千次阅读 2020-02-08 17:34:48
    业务需求:按时间段连续统计每日销售额,如出现无销售情况,填充日期销售额为0 思路:创建储存过程,JPA调用,Service层使用工具类转换查询到的结果集 1、创建储存过程 储存过程查询结果如图: 2、Jpa...
  • 事实上将来数据量变得足够大的时候,远端单点数据获取和处理将变得困难,庞大的数据量导致业务处理会变得越来越慢,分布式储存和处理变得越来越有必要。今天我们就介绍一下基于MetaID的分布式储存方案,ShowMANDB,...
  • 物料收、发、储存、防护的管理流程DOC以规范化构造端到端的卓越业务流程为中心,致力于打造最强、最好的...该文档为物料收、发、储存、防护的管理流程DOC,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以...
  • 为什么要数据云储存?

    2020-07-16 18:44:17
    当计划外的业务有需要存储的时候,数据存储容量的能力成了救命的稻草。同样,当人工智能应用于物联网数据和其他大规模数据集而开始考虑建立数据湖时,公共云的无限存储容量发挥了作用。数据湖的设想还处于“萌芽阶段...
  • mysql 储存过程的特点 (译自mysql官方文档)使业务逻辑可以在不同语言编写的客户端程序中调用用在极端要求安全性的场合 比如银行全部使用储存过程来处理业务 这样可以保持一个一致而且安全的环境 储存过程可以保证...
  • 版本信息:SpringBoot v2.1.6JPA2.2.4SQLServer 2012业务需求:按时间段连续统计每日销售额,如出现无销售情况,填充日期销售额为0思路:创建储存过程,JPA调用,Service层使用工具类转换查询到的结果集1、创建储存...
  • 阿里云的OSS相对于传统的服务器储存是方便的多,而且也比FTP和SFTP快多了。也不需要考虑很多上传问题。 根据业务可以分为前端上传和后端上传。各有各的好处,比如前端上传肯定是可以降低服务器的压力的,后端上传的...
  • 阿里云OSS,搭建自己的云储存

    万次阅读 2017-01-09 17:51:39
    尤其是有下载、视频、音乐等业务的网站来说,那更是一笔庞大的开销。 较比之前,我们可以通过各大厂商提供的网络云盘进行数据的储备。但是进来由于国家的某些政策,各大厂商纷纷关闭了网盘服务。目前也就百度云还能...
  • ① cookie大小限制在4k左右,不适合存业务数据 ② cookie每次随HTTP事务一起发送,浪费带宽 我们是做移动项目的,所以这里真实适合使用的技术是localstorage,localstorage可以说是对cookie的优化,使用它可以方便在...
  • OpenERP在哪储存附件?

    2019-10-01 15:31:38
    我们知道对OpenERP中的每个内部对象(比如:业务伙伴,采购订单,销售订单,发货单,等等)我们都可以添加任意的附件,如图片,文档,视频等。那么这些附件在OpenERP内部是如何管理的呢? 默认情况下,这些附件在...
  • 储存与更新 access_token

    2016-12-15 23:37:00
    做微信的项目,一开始就是 access...而其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则会造成access_token覆盖而影响业务;2、目前access_token的有效期通过返回的expire_in来...
  • Tektronix新推出2信道与4信道的TDS1000B和TDS2000B系列数字储存示波器,据悉,新产品频宽达200MHz、单通道最大取样率达每秒2GS,并具备USB储存和PC联机能力;另外,Tektronix还为新产品提供终生保修,以及...
  • 第一条 仓库是企业物资供应体系的一个重要组成部分,是企业各种物资周转储备的环节,同时担负着物资管理的多项业务职能。仓库的主要任务是:保管好库存物资,做到数量准确,质量完好,确保安全,收发迅速,面向生产...
  • Tektronix新推出2信道与4信道的TDS1000B和TDS2000B系列数字储存示波器,据悉,新产品频宽达200MHz、单通道最大取样率达每秒2GS,并具备USB储存和PC联机能力;另外,Tektronix还为新产品提供终生保修,以及...
  • 数据储存---SQLtie

    2016-08-20 08:49:40
    SQLite主要特点: ...通过数据库上的独占性和共享锁来实现独立业务处理多个进程可以在同一时间从同一数据库读取数据,但只有一个可以写入数据。 关于SQLite的数据类型:  据SQLtie支持NULL(空值)、INTE
  • 呵呵,因实施现场需要我们研发人员给他们一个批量删除业务数据的SQL,我把他写成存储过程来用,存储过程如下:--创建存储过程删除入围管理和合作协议相关业务数据--作者:zengqiangIF EXISTS (SELECT name FROM ...
  • Sql Server中限定用户...并新建一个登录名,供对方连接到数据库 现在问题出来了,我们提供的储存过程都比较复杂(业务本身复杂造成),里面需要访问大量表、储存过程、函数等,我们只希望对方使用这几个储存过程,...
  • 开发四年只会写业务代码,分布式高并发都不会还做程序员? Apache Jackrabbit 2.18.1是一个增量版...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 977
精华内容 390
关键字:

储存业务