在项目中使用mybatis作为持久层框架,mysql数据库。项目上线前,DBA要求咱们将每张数据库表中的字段都设置默认值和not null。以前项目中有一些insert语句是将表中全部字段都列出来,而后把它作为一个通用的插入语句来使用。举个简单的例子:假如一张数据库表blog中有以下几个字段:id,title,content,author,除id外,每一个字段都设置了默认值Empty String(空字符串),写的一个insert语句是这样的:
mysql
- <insert id="addOneBlog" parameterType="main.Blog">
- insert into blog(title,author,content)
- values(#{title},#{author},#{content})
- </insert>
原觉得有这么一个insert语句就万事大吉了,咱们觉得,之后作插入操做的时候,不管有多少个字段,都使用这一个insert语句,若是字段没有值,就会被赋值为mysql字段的默认值。。。
但事实证实,根本不是这样的。
当咱们只给title字段赋值,而后执行一个insert语句时,mybatis立刻报出这样的异常:
sql
- Caused by: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Column 'content' cannot be null
显然,全部字段规定了not null,看来按照这种insert的方法,未赋值的字段并无赋值为mysql的默认值。
那么若是把数据库字段的not null限制去掉呢?
再次执行刚才的insert操做,此次没有抛出异常,但查看数据库后,咱们发现,新插入的表记录中,没有赋值的字段仍然不是mysql的默认值,而是null值。
因此,按照上面所谓的通用insert语句,是没法让未赋值字段的值变为mysql默认值的。这种insert语句没法作到通用。具体解决方案数据库
上一篇简单介绍了一个mysql的问题:字段默认值在使用全字段insert的时候,可能并不会生效。在使用mybatis时,虽然须要本身写sql,但相比原始jdbc的方式来讲,有一个很好的优点——动态sql。针对前一篇文章提出的问题,mybatis的动态sql能够很好地解决这个问题。mybatis
1.问题分析框架
上一篇文章中描述的问题,是因为咱们误将一个包含全部字段的insert语句作为通用的insert。那么显而易见,解决此问题的方法是,咱们须要针对不一样的业务需求,严格按照须要插入的字段来写不一样的sql,不须要插入的字段,在insert语句中不可以出现。举例上一篇的blog表例子说明,假如咱们有一个插入操做,只须要在插入时给author赋值,那么sql能够这么写:ide
- <insert id="addOneBlog" parameterType="main.Blog">
- insert into blog(author)
- values (#{author})
- </insert>
这个方法虽然奏效,但在实际项目开发中,为了开发效率的须要,咱们仍然但愿可以有一个通用的insert语句,供全部涉及单表插入操做的业务调用。刚才说过,mybatis有一个很是强大的特点功能:动态sql,使用动态sql便可解决此问题。spa
2.<sql>、<include>、<trim>标签简介blog
mybatis的动态sql功能包含了不少实用的标签:<sql>标签表示一个sql片断,使用此标签不只能够重用不少sql代码,并且使sql语句更清晰;定义好<sql>标签后,在调用它的地方使用<include>标签,便可将定义好的sql片断拼接进来;<trim>标签能够在标签体内的sql片断首尾任意添加或覆盖字符。开发
3.问题解决字符串
先上代码:
- <sql id="blogColumns">
- <trim suffixOverrides=",">
- <if test="title != null">title,</if>
- <if test="author != null">author,</if>
- <if test="content != null">content</if>
- </trim>
- </sql>
- <sql id="blogValues">
- <trim suffixOverrides=",">
- <if test="title != null">#{title},</if>
- <if test="author != null">#{author},</if>
- <if test="content != null">#{content}</if>
- </trim>
- </sql>
- <insert id="addOneBlog" parameterType="Blog">
- insert into blog(<include refid="blogColumns"/>)
- values (<include refid="blogValues"/>)
- </insert>
对于blog表,上面这段代码便可实现咱们想要的insert重用,无论插入的字段有多少,咱们均可以使用它来实现全部单表insert操做。上面代码中,先定义两个sql片断,分别表明insert语句中的字段列表和参数列表,并使用<trim>标签去除片断首尾可能出现的多余的“,”字符。最后写一个简单的insert,并将上面的sql片断拼接进来。
4.结尾
关于mybatis的动态sql,它有不少强大的,可高度重用sql的功能。你们若是对一些标签的做用不太清楚,请期待我后续的博文。做为一个半自动的持久层框架,咱们虽然须要本身写sql语句,但mybatis的动态sql可以最大限度地减小咱们的代码量,这也是在ORM横行的JavaEE世界里,mybatis可以独树一帜的缘由。