`

java程序员最容易犯的错

 
阅读更多

Java程序员编程时需要混合面向对象思维和一般命令式编程的方法,能否完美的将两者结合起来完全得依靠编程人员的水准:

    技能(任何人都能容易学会命令式编程)
    模式(有些人用“模式-模式”,举个例子,模式可以应用到任何地方,而且都可以归为某一类模式)
    心境(首先,要写个好的面向对象程序是比命令式程序难的多,你得花费一些功夫)

但当Java程序员写SQL语句时,一切都不一样了。SQL是说明性语言而非面向对象或是命令式编程语言。在SQL中要写个查询语句是很简单的。但在Java里类似的语句却不容易,因为程序员不仅要反复考虑编程范式,而且也要考虑算法的问题。

下面是Java程序员在写SQL时常犯的错误(没有特定的顺序):


1.忘掉NULL

Java程序员写SQL时对NULL的误解可能是最大的错误。也许是因为(并非唯一理由)NULL也称作UNKNOWN。如果被称作UNKNOWN,这还好理解些。另一个原因是,当你从数据库拿东西或是绑定变量时,JDBC将SQL NULL 和Java中的null对应了起来。这样导致了NULL = NULL(SQL)和null=null(Java)的误解。

对于NULL最大的误解是当NULL被用作行值表达式完整性约束条件时。

另一个误解出现在对于NULL 在 NOT IN anti-joins的应用中。

解决方法:

好好的训练你自己。当你写SQL时要不停得想到NULL的用法:

    这个NULL完整性约束条件是正确的?
    NULL是否影响到结果?


2.在Java内存中处理数据

很少有Java开发者能将SQL理解的很好.偶尔使用的JOIN,还有古怪的UNION,好吧.但是对于窗口函数呢?还有对集合进行分组呢?许多的Java开发者将SQL数据加载到内存中,将这些数据转换成某些相近的集合类型,然后再那些集合上面使用边界循环控制结构(至少在Java8的集合升级以前)执行令人生厌的数学运算.

但是一些SQL数据库支持先进的(而且是SQL标准支持的!)OLAP特性,这一特性表现更好而且写起来也更加方便.一个(并不怎么标准的)例子就是Oracle超棒的MODEL分句.只让数据库来做处理然后只把结果带到Java内存中吧.因为毕竟所有非常聪明的家伙已经对这些昂贵的产品进行了优化.因此实际上,通过将OLAP移到数据库,你将获得一下两项好处:

    便利性.这比在Java中编写正确的SQL可能更加的容易.
    性能表现.数据库应该比你的算法处理起来更加快.而且更加重要的是,你不必再去传递数百万条记录了.

完善的方法:

每次你使用Java实现一个以数据为中心的算法时,问问自己:有没有一种方法可以让数据库代替为我做这种麻烦事.


3. 使用UNION代替UNION ALL

太可耻了,和UNION相比UNION ALL还需要额外的关键字。如果SQL标准已经规定了支持,那么可能会更好点。

    UNION(允许重复)
    UNION DISTINCT (去除了重复)

移除重复行不仅很少需要(有时甚至是错的),而且对于带很多行的大数据集合会相当慢,因为两个子select需要排序,而且每个元组也需要和它的子序列元组比较。

注意即使SQL标准规定了INTERSECT ALL和EXCEPT ALL,很少数据库会实现这些没用的集合操作符。

处理方法:
每次你写UNION语句时,考虑实际上是否需要UNION ALL语句。


4.通过JDBC分页技术给大量的结果进行分页操作

大部分的数据库都会支持一些分页命令实现分页效果,譬如LIMIT..OFFSET,TOP..START AT,OFFSET..FETCH语句等。即使没有支持这些语句的数据库,仍有可能对ROWNUM(甲骨文)或者是ROW NUMBER() OVER()过滤(DB2,SQL Server2008等),这些比在内存中实现分页更快速。在处理大量数据中,效果尤其明显。

纠正:



仅仅使用这些语句,那么一个工具(例如JOOQ)就可以模拟这些语句的操作。


5.在java内存中加入数据

从SQL的初期开始,当在SQL中使用JOIN语句时,一些开发者仍旧有不安的感觉。这是源自对加入JOIN后会变慢的固有恐惧。假如基于成本的优化选择去实现嵌套循环,在创建一张连接表源前,可能加载所有的表在数据库内存中,这可能是真的。但是这事发生的概率太低了。通过合适的预测,约束和索引,合并连接和哈希连接的操作都是相当的快。这完全是是关于正确元数据(在这里我不能够引用Tom Kyte的太多)。而且,可能仍然有不少的Java开发人员加载两张表通过分开查询到一个映射中,并且在某种程度上把他们加到了内存当中。

纠正:

假如你在各个步骤中有从各种表的查询操作,好好想想是否可以表达你的查询操作在单条语句中。


6.在一个临时的笛卡尔积集合中使用 DISTINCT 或 UNION 消除重复项

通过复杂的连接,人们可能会对SQL语句中扮演关键角色的所有关系失去概念。特别的,如果这涉及到多列外键关系的话,很有可能会忘记在JOIN .. ON子句中增加相关的判断。这会导致重复的记录,但或许只是在特殊的情况下。有些开发者因此可能选择DISTINCT来消除这些重复记录。从三个方面来说这是错误的:

    它(也许)解决了表面症状但并没有解决问题。它也有可能无法解决极端情况下的症状。
    对具有很多列的庞大的结果集合来说它很慢。DISTINCT要执行ORDER BY操作来消除重复。
    对庞大的笛卡尔积集合来说它很慢,还是需要加载很多的数据到内存中。

解决方法:

根据经验,如果你获得了不需要的重复记录,还是检查你的JOIN判断吧。可能在某个地方有一个很难觉察的笛卡尔积集合。


7. 不使用MERGE语句

这并不是一个过失,但是可能是缺少知识或者对于强悍的MERGE语句信心不足。一些数据库理解其它形式的更新插入(UPSERT)语句, 如 MYSQL的重复主键更新语句,但是MERGE在数据库中确是很强大,很重要,以至于大肆扩展SQL标准,例如SQL SERVER。

解决之道:

如果你使用像联合INSERT和UPDATE或者联合SELECT .. FOR UPDATE然后在INSERT或UPDATE等更新插入时,请三思。你完全可以使用一个更简单的MERGE语句来远离冒险竞争条件。


8. 使用聚合函数代替窗口函数(window functions)

在介绍窗口函数之前,在SQL中聚合数据意味着使用GROUP BY语句与聚合函数相映射。在很多情形下都工作得很好,如聚合数据需要浓缩常规数据,那么就在join子查询中使用group查询。

但是在SQL:2003中定义了窗口函数,这个在很多主流数据库都实现了它。窗口函数能够在结果集上聚合数据,但是却没有分组。事实上,每个窗口函数都有自己的、独立的PARTITION BY语句,这个工具对于显示报告太TM好了。

使用窗口函数:

    使SQL更易读(但在子查询中没有GROUP BY语句专业)
    提升性能,像关系数据库管理系统能够更容易优化窗口函数

解决方法:



当你在子查询中使用GROUP BY语句时,请再三考虑是否可以使用窗口函数完成。


9. 使用内存间接排序

SQL的ORDER BY语句支持很多类型的表达式,包括CASE语句,对于间接排序十分有用。你可能重来不会在Java内存中排序数据,因为你会想:

    SQL排序很慢
    SQL排序办不到

处理方法:



如果你在内存中排序任何SQL数据,请再三考虑,是否不能在数据库中排序。这对于数据库分页数据十分有用。


10. 一条一条的插入大量纪录

JDBC ”懂“批处理(batch),你应该不会忘了它。不要使用INSERT语句来一条一条的出入成千上万的记录,(因为)每次都会创建一个新的PreparedStatement对象。如果你的所有记录都插入到同一个表时,那么就创建一个带有一条SQL语句以及附带很多值集合的插入批处理语句。你可能需要在达到一定量的插入记录后才提交来保证UNDO日志瘦小,这依赖于你的数据库和数据库设置。

处理方法:
总是使用批处理插入大量数据。
分享到:
评论

相关推荐

    Java程序员容易犯的10个错误

    Java程序员容易犯的10个错误,Arrays.asList() 会返回一个ArrayList,这是Arrays里内嵌的一个私有静态类,而并不是java.util.ArrayList类java.util.Arrays.ArrayList 有set(), get(), contains()方法,但并支持添加...

    Java程序最容易犯的21种错误

    客观的讲述了作为一个java程序员在日常工作中由于各种原因经常犯下的错误

    JAVA程序员必需搞懂的问题

    JAVA程序员必需搞懂的问题,描述一些Java程序员需注意的问题一些容易犯的错误。

    JAVA程序员必读基础篇

    JAVA是有SUN公司开发的新一代编程语言,它可以用在各种不同的机器、操作系统的网络环境中...所以作为Internet应用的开发技术人员不可不看JAVA,而JAVA程序不可不先从基础学起,这正是JAVA程序员必读:基础篇的用意。

    Java程序员容易犯的10大低级错误

    主要介绍了Java程序员容易犯的10大低级错误,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

    Java 程序员容易犯的10个SQL错误

    本文介绍了Java 程序员容易犯的10个SQL错误。具有很好的参考价值,下面跟着小编一起来看下吧

    Java程序员常犯的五个错误

    总结以前经验针对java编程的一些习惯,给出一些关于java编程的建议: 当你开始成为一个程序员的时候,在编程的时候很容易陷入下面所述的一些坏习惯,下面把Java程序员常犯的五个错误整理如下,需要的朋友可以参考下

    java常犯的错误

    介绍了java程序员在写程序的时候容易犯的10种错误

    java是什么.avi

    java学习第一天,讲解java是什么 本章学习要点 了解 Java 语言的版本及特点 了解学习 Java 的方法 掌握 JDK 的安装 掌握环境变量的配置 熟悉 Java 程序的编写、编译和运行过程 ...15.Java程序员学习路线

    java程序中容易出错的地方

    很容易错的地方,听说一些老程序员也经常犯的错误哦,希望大家编程 的时候尽量不要错了

    程序员面试金典-卷二

    面试者最容易犯的10个错误不要因为这些常见的错误而与成功失之交臂。要了解面试者常犯的一些错误,学会如何避免这些问题。面试准备的若干策略不要因为沉溺在无穷无尽的面试题中而错过了最重要的求职建议。这些策略和...

    JAVA面试题解惑系列

    java面试中经常会被问到的问题,有些也是程序员经常容易犯错误的,涵盖java的知识点比较全

    JAVA自学之路

    经常的进行知识难点的查询,如果一个问题牵扯的面比较广,就干脆到网上搜索一些相关的专题,比如“java 乱码 mysql” “oracle 创建用户”等等,如果有必要,不要犯懒,勤动手写一些小小的测试程序,来弄明白知识点...

    程序员为什么还要刷题-typescript-summary:供初学者了解TS的简短摘要!

    成为容易犯错误的地方。 TS 负责编译(转译)代码,并为程序员提供更好的代码编写环境。 写作环境? 是的,当您想在浏览器上运行 TS 代码时,它最终会被转换为 JS。 看下面的例子: 左边是TS代码,右边是转译后的JS...

    xml与反射.txt

    的,然后直接复制修改,由于容易犯各种低级的错误(大小写啊,多一个或少一个字母啊……),一个错误就可以让你找半天。 有了java反射机制,什么都好办了,只需要写一个dao类,四个方法,增删改查,传入不同的对象,...

    【03-流程控制与数组】

    •初学者使用for循环时也容易犯一个错误,他们以为只要在for后的括号内控制了循环循环迭代语句就万无一失,  但实际情况则不是这样的。 for循环的分号 •for 循环圆括号中只有两个分号是必须的,初始化...

    sesvc.exe 阿萨德

    Java JavaScript PHP iOS Android HTML5 CSS3 Linux C++ Python C# Node.Js 一文让你彻底理解 Java HashMap 和 ConcurrentHashMap 2018-07-25 分类:JAVA开发、编程开发、首页精华0人评论 ...

    MathExtensions:Jai的进阶数学功能

    该项目的目标是逐步为Jai编写一个综合的数学库,类似于Gnu科学库或Java Apache Math。 重点在于首先提供功能,其次才是性能。 随时添加功能和性能升级。 警告 我不是一个很好的程序员。 我犯了错误,编写了不理想...

    Python 2.5

    如果人工来做,这会是一个很繁琐而且容易犯错误的过程,你总会遗漏东西,到头来你还得重做以前的工作。Python对列表和字典的本地支持使复杂的数据转换更加容易。而且这种交互式模式可以让编程人员在转换过程的每一...

Global site tag (gtag.js) - Google Analytics