MySQL5.7 sql_mode only_full_group_by

1 MySQL 官方文档:

https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html

https://blog.csdn.net/kk185800961/article/details/79426041

https://blog.csdn.net/wangyunfeis/article/details/77911704

2 执行的SQL:

select t3.attribute_value_id,
 t3.attribute_value_code
 from category_rel_attribute t1
 INNER JOIN
 category_rel_attribute_rel_value t2 on t1.category_attribute_id=
 t2.category_attribute_id
 INNER JOIN
 category_attribute_value_code_config t3 on
 t2.category_attribute_value_id= t3.attribute_value_id
 where
 t1.category_id= 1
 and t1.is_sku_attr= 'Y'
 GROUP BY
 t2.category_attribute_value_id

3 报错

Expression #2 of SELECT list is not in GROUP BY 
clause and contains nonaggregated column 
'pms.t3.attribute_value_code' which is not functionally 
dependent on columns in GROUP BY clause; this is 
incompatible with sql_mode=only_full_group_by

4 select @@sql_mode

 

5 去掉ONLY_FULL_GROUP_BY

mysql> set sql_mode=’STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION’;

Query OK, 0 rows affected (0.01 sec)

lombok介绍

1 lombok介绍
lombok 提供了简单的注解Annotation的形式来帮助我们简化消除一些必须有但显得很臃肿的 java 代码,比如 javabean 属性的get 方法,set方法,无参数构造,全部参数的构造函数等
2 lombok 使用
lombok是基于注解的,我们先看看它常用注解的作用
@Data   :注解在类上;提供类所有属性的getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法         @Setter:注解在属性上;为属性提供 setting 方法         @Getter:注解在属性上;为属性提供 getting 方法         @Log4j :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象         @NoArgsConstructor:注解在类上;为类提供一个无参的构造方法         @AllArgsConstructor:注解在类上;为类提供一个全参的构造方法
2.1 使用lombok前的做法
public class CarModelDO implements Serializable {
    /**
    *
    */
   private static final long serialVersionUID = 1L;
   private String id;
    private String brand;
    private String brandCode;
    private String series;
    private String seriesCode;
    private String seriesRemark;
    private int factor_1;
    private Date dtCreate;
    private Date dtUpdate;
   public String getId() {
      return id;
   }
   public void setId(String id) {
      this.id = id;
   }
   public String getBrand() {
      return brand;
   }
   public void setBrand(String brand) {
      this.brand = brand;
   }
   public String getBrandCode() {
      return brandCode;
   }
   public voidsetBrandCode(String brandCode) {
      this.brandCode = brandCode;
   }
   public String getSeries() {
      return series;
   }
   public void setSeries(Stringseries) {
      this.series = series;
   }
   public String getSeriesCode() {
      return seriesCode;
   }
   public voidsetSeriesCode(String seriesCode) {
      this.seriesCode = seriesCode;
   }
   public String getSeriesRemark() {
      return seriesRemark;
   }
   public voidsetSeriesRemark(String seriesRemark) {
      this.seriesRemark = seriesRemark;
   }
   public int getFactor_1() {
      return factor_1;
   }
   public void setFactor_1(int factor_1) {
      this.factor_1 = factor_1;
   }
   public Date getDtCreate() {
      return dtCreate;
   }
   public void setDtCreate(DatedtCreate) {
      this.dtCreate = dtCreate;
   }
   public Date getDtUpdate() {
      return dtUpdate;
   }
   public void setDtUpdate(DatedtUpdate) {
      this.dtUpdate = dtUpdate;
   }
   
}
可以看到这是我们常规的写法
2.2 使用lombok做法
 
 
 @Data
public class CarModelDOimplements Serializable {
    private String id;
    private String brand;
    private String brandCode;
    private String series;
    private String seriesCode;
    private String seriesRemark;
    private int factor_1;
    private Date dtCreate;
    private Date dtUpdate;
}
 
反编译后的代码:
public class CarModelDOimplements Serializable {
   private String id;
   private String brand;
   private String brandCode;
   private String series;
   private String seriesCode;
   private String seriesRemark;
   private int factor_1;
   private Date dtCreate;
   private Date dtUpdate;
   public String toString() {
      return “CarModelDO(id=” +getId() + “, brand=” + getBrand() + “,brandCode=” + getBrandCode() + “,series=”
            + getSeries() + “,seriesCode=” + getSeriesCode() + “,seriesRemark=” + getSeriesRemark()
            + “,factor_1=” + getFactor_1() + “,dtCreate=” + getDtCreate() + “,dtUpdate=” + getDtUpdate() + “)”;
   }
   public inthashCode() {
      int PRIME = 59;
      int result = 1;
      Object $id =getId();
      result = result * 59 + ($id == null ? 43 : $id.hashCode());
      Object $brand =getBrand();
      result = result * 59 + ($brand == null ? 43 : $brand.hashCode());
      Object $brandCode =getBrandCode();
      result = result * 59 + ($brandCode == null ? 43 : $brandCode.hashCode());
      Object $series =getSeries();
      result = result * 59 + ($series == null ? 43 : $series.hashCode());
      Object $seriesCode =getSeriesCode();
      result = result * 59 + ($seriesCode == null ? 43 : $seriesCode.hashCode());
      Object $seriesRemark =getSeriesRemark();
      result = result * 59 + ($seriesRemark == null ? 43 : $seriesRemark.hashCode());
      result = result * 59 +getFactor_1();
      Object $dtCreate =getDtCreate();
      result = result * 59 + ($dtCreate == null ? 43 : $dtCreate.hashCode());
      Object $dtUpdate =getDtUpdate();
      result = result * 59 + ($dtUpdate == null ? 43 : $dtUpdate.hashCode());
      return result;
   }
   protected booleancanEqual(Object other) {
      return other instanceofCarModelDO;
   }
   public boolean equals(Objecto) {
      if (o == this) {
         return true;
      }
      if (!(o instanceofCarModelDO)) {
         return false;
      }
      CarModelDO other =(CarModelDO) o;
      if (!other.canEqual(this)) {
         return false;
      }
      Object this$id =getId();
      Object other$id = other.getId();
      if (this$id == null ? other$id != null : !this$id.equals(other$id)) {
         return false;
      }
      Object this$brand =getBrand();
      Object other$brand = other.getBrand();
      if (this$brand == null ? other$brand != null : !this$brand.equals(other$brand)) {
         return false;
      }
      Object this$brandCode =getBrandCode();
      Object other$brandCode = other.getBrandCode();
      if (this$brandCode == null ? other$brandCode != null : !this$brandCode.equals(other$brandCode)) {
         return false;
      }
      Object this$series =getSeries();
      Object other$series = other.getSeries();
      if (this$series == null ? other$series != null : !this$series.equals(other$series)) {
         return false;
      }
      Object this$seriesCode =getSeriesCode();
      Object other$seriesCode = other.getSeriesCode();
      if (this$seriesCode == null ? other$seriesCode != null : !this$seriesCode.equals(other$seriesCode)) {
         return false;
      }
      Object this$seriesRemark =getSeriesRemark();
      Object other$seriesRemark = other.getSeriesRemark();
      if (this$seriesRemark == null ? other$seriesRemark != null : !this$seriesRemark.equals(other$seriesRemark)) {
         return false;
      }
      if(getFactor_1() != other.getFactor_1()) {
         return false;
      }
      Object this$dtCreate =getDtCreate();
      Object other$dtCreate = other.getDtCreate();
      if (this$dtCreate == null ? other$dtCreate != null : !this$dtCreate.equals(other$dtCreate)) {
         return false;
      }
      Object this$dtUpdate =getDtUpdate();
      Object other$dtUpdate = other.getDtUpdate();
      return this$dtUpdate == null ? other$dtUpdate == null : this$dtUpdate.equals(other$dtUpdate);
   }
   public voidsetDtUpdate(Date dtUpdate) {
      this.dtUpdate = dtUpdate;
   }
   public voidsetDtCreate(Date dtCreate) {
      this.dtCreate = dtCreate;
   }
   public voidsetFactor_1(int factor_1) {
      this.factor_1 = factor_1;
   }
   public voidsetSeriesRemark(String seriesRemark) {
      this.seriesRemark = seriesRemark;
   }
   public voidsetSeriesCode(String seriesCode) {
      this.seriesCode = seriesCode;
   }
   public voidsetSeries(String series) {
      this.series = series;
   }
   public voidsetBrandCode(String brandCode) {
      this.brandCode = brandCode;
   }
   public voidsetBrand(String brand) {
      this.brand = brand;
   }
   public voidsetId(String id) {
      this.id = id;
   }
   public Date getDtUpdate() {
      return this.dtUpdate;
   }
   public Date getDtCreate() {
      return this.dtCreate;
   }
   public intgetFactor_1() {
      return this.factor_1;
   }
   public StringgetSeriesRemark() {
      return this.seriesRemark;
   }
   public StringgetSeriesCode() {
      return this.seriesCode;
   }
   public String getSeries(){
      return this.series;
   }
   public StringgetBrandCode() {
      return this.brandCode;
   }
   public String getBrand() {
      return this.brand;
   }
   public String getId() {
      return this.id;
   }
}
 
和上面2.1的代码是一样的,而且还给我们生成了其它方法。
其它Annotaion 使用参照上面的用法。
2.3 开发使用方法
1 编译类路径下增加 lombok.jar,下面是maven方式
<dependency>
<groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.8</version>
    <scope>provided</scope>
 </dependency>
2 在需要使用javabean类上加上注解
3 java源代码编译后经过得到对应的字节码,见反编译
3 Mac 下eclipse 安装lombok
eclipse编译java源文件使用的是EclipseCompiler for Java (ECJ).要想使ECJ支持lombok,得进行设置,在Eclipse安装目录中eclipse.app的eclipse.ini文件中添加如下两行设置,以我的机器为例,
在/usr/local/eclipse-jee/Eclipse.app/Contents/MacOS/eclipse.ini最后增加如下两行
-Xbootclasspath/a:lombok.jar
-javaagent:/usr/local/eclipse-jee/lombok.jar
Intellij Idea 可以选择编译工具为oraclejavac。
4 原理介绍
2005.2.1 Sun公司在提交了JSR 269,用于支持在编译期对annotation进行处理(this JSRwill define APIs to allow annotation processors to be created using a standardpluggable API. This will simplify the task of creating annotation processorsand will also allow automation of the discovery of appropriate annotationprocessors for a given source file.)
自从java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。 而 Lombok就是实现该规范,规范介绍:https://jcp.org/en/jsr/detail?id=269
oracle JDK编译java源代码的简单介绍图:
1.分析和输入到符号表(Parse and Enter)
   Parse过程所做的工作有词法和语法分析。词法分析要完成将代码字符串转变为Token序列。语法分析则是根据语法将Token序列生成抽象语法树。
   Enter过程将符号输入到符号表,通常包括确定类的超类型和接口、根据需要添加默认构造器、将类中出现的符号输入类自身的符号表中等。
2.注解处理(Annotation Processing)
   该步骤主要用于处理用户自定义的annotation,可能带来的好处是基于annotation来生成附加的代码或进行一些特殊的检查,从而节省一些共同的代码的编写。此功能基于JSR269,在Sun JDK6 中提供了支持,在注解处理完之后,再次进入上一步骤。
3.语义分析和生成class文件(Analyse and Generate)
   该步骤基于抽象语法树进行一系列的语义分析,包括将语法树中的名字、表达式等元素与变量、方法、类型等联系在一起;检查变量使用前是否已声明;推导泛型方法的类型参数;检查类型匹配性;进行常量折叠;检查所有语句都可到达;检查所有checked exception 都被捕获或抛出;检查变量的确定性赋值(例如有返回值的方法必须确定有返回值);检查变量的确定性不重复赋值(例如声明为final的变量等);解除语法糖(消除if(false){…}形式的无用代码;将泛型Java转为普通Java;将含有语法糖的语法树改为含有简单语言结构的语法树,例如foreach循环、自动装箱/拆箱等)。
    在完成了语义分析后,开始生成class文件,生成的步骤为:首先将实例成员初始化器收集到构造器中,将静态成员初始化收集为<clinit>();接着将抽象语法树生成字节码,采用的方法为后序遍历语法树,并进行最后的少量代码转换(例如String相加转变为StringBuilder操作);最后从符号表生成class文件。
4.class文件内容
   class文件中并不仅仅存放了字节码,还存放了很多辅助JVM来执行class的附加信息,一个class文件包含了以下信息:
    1)结构信息
     包括class文件格式版本号及各部分的数量与大小的信息
    2)元数据
     简单来说,可以认为元数据对应的就是Java源码中“声明”与“常量”的信息,主要有:类、继承的超类、实现的接口声明信息、域与方法声明信息和常量池。
    3)方法信息
      方法信息对应的就是Java源码中的“语句”与“表达式”对应的信息,主要有:字节码、异常处理器表、求值栈与局部变量区大小、求值栈的类型记录、调试用符号信息。

大型项目结构参考

根据以往的项目经验总结了一份项目结构图,以供参考,欢迎大家一起交流。
1 工程图预览
2 具体模块介绍
为表现清晰,图中的依赖都表现为直接依赖,整个项目的结构为maven的项目,
注意:maven的依赖是可以传递的,比方说A->B->C->D,A对B是直接依赖,A->C和D是传递依赖,也就是说A也依赖C和D模块。
common模块
这个是整个工程的通用模块,不依赖其它模块,主要功能可以提供工具类,日志类等
dao模块,database acessobject,主要是访问数据库和包含数据库的DO(database object),一般是一个表一个访问类,可以依赖model模块,model模块主要是领域模型的声明
remoting模块:
主要功能类似于数据源,主要是以rpc或http等方式远程调用外部的接口,诸如dubbo(阿里巴巴SOA服务化治理框架),http方式,也可以调用外部的webservice接口,访问mongodb数据库等。
Model模块:model模型层,主要是对外服务接口的领域对象声明,项目内部也是可以用的。
Service模块:服务接口声明层,主要是对外服务接口的声明,如果我们用dubbo的话是非常方便的,调用方之间依赖项目的这个组件即可,这个模块一般是在公司内部以第三方库的模式发布到maven仓库,其依赖的模块为model模块,返回的结果和接收的参数对象(自定义的类),这里为什么service和model要分开呢,因为我们在做服务化的时候,服务接口有变化(升级,降级,下线)的时候,有可能是不需要改动接口的,而是接口的返回结果或接口参数(自定义类)增加一个或几个字段即可,而服务接口不需要改动。
Biz-common模块:通用的业务模块:诸如日志拦截器,权限的校验,通用的MQ调用等,通用等业务功能如:访问统一的用户信息,权限信息等。这个不是必须的,一般适用于大型的业务项目
Biz-module1:具体的业务模块实现,比如实现service模块的接口声明,访问数据库和远程接口等。
Biz-module2:和biz-module1模块功能类似,在大项目的开发中,就需要划分很多的业务模块和分模块来开发了,可以根据项目业务情况自行决定。
 Web模块:web模块一般是项目的应用层【biz层实现远程接口的业务层也是可以直接对外暴露接口的,如dubbo接口,hessian接口】,包含页面控制层和试图层,WEB模块也可以多是多个,这个也是表现在大型项目的开发中

mybatis invalid comparison: java.util.Date and java.lang.String 异常

1 错误详情

mybatis invalid comparison: java.util.Date and java.lang.String

Caused by: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
 at org.apache.ibatis.ognl.OgnlOps.compareWithConversion(OgnlOps.java:92)
 at org.apache.ibatis.ognl.OgnlOps.isEqual(OgnlOps.java:142)
 at org.apache.ibatis.ognl.OgnlOps.equal(OgnlOps.java:794)
 at org.apache.ibatis.ognl.ASTNotEq.getValueBody(ASTNotEq.java:53)
 at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
 at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
 at org.apache.ibatis.ognl.ASTAnd.getValueBody(ASTAnd.java:61)
 at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
 at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
 at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:494)
 at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:458)
 at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:44)
 at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32)
 at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34)
 at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
 at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55)
 at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
 at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41)
 at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:280)
 at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:80)
 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120)
 ... 7 more

原因就是mybatis 3.4.0中比较时间有个有bug,不能把时间当字符串比较,去掉

nextExecuteTime != '' 的判断即可