代码生成器原理和使用、QBC、Mybattis扩展
QBC(Query By Criteria) API提供了检索对象的另一种方式,它主要由Criteria接口、Criterion接口和Expresson类组成,它支持在运行时动态生成查询语句。
Hibernate中共提供了三种检索方式:HQL(Hibernate Query Language)、QBC、QBE(Query By Example)。
QBC检索步骤:
1、调用Session的createCriteria()方法创建一个Criteria对象。
2、设定查询条件。Restrictions类提供了一系列用于设定查询条件的静态方法,
这些静态方法都返回Criterion实例,每个Criterion实例代表一个查询条件。
Criteria的add()方法用于加入查询条件。
3、调用Criteria的list()方法执行查询语句。该方法返回List类型的查询结果,在
List集合中存放了符合查询条件的持久化对象。
代码生成器:
从后往前进行分析:
零、以tb_brand表为例:
CREATE TABLE `tb_brand` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL COMMENT '品牌名称',
`first_char` varchar(1) DEFAULT NULL COMMENT '品牌首字母',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;
一、dao层的映射配置为文件 TbBrandMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.pinyougou.mapper.TbBrandMapper" > <!-- 数据库中查询的字段和pojo类属性的映射 --> <resultMap id="BaseResultMap" type="com.pinyougou.pojo.TbBrand" > <id column="id" property="id" jdbcType="BIGINT" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="first_char" property="firstChar" jdbcType="VARCHAR" /> </resultMap> <!-- 添加的 WHERE 子句 --> <sql id="Example_Where_Clause" > <where > <foreach collection="oredCriteria" item="criteria" separator="or" > <if test="criteria.valid" > <trim prefix="(" suffix=")" prefixOverrides="and" > <foreach collection="criteria.criteria" item="criterion" > <choose > <when test="criterion.noValue" > and ${criterion.condition} </when> <when test="criterion.singleValue" > and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue" > and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue" > and ${criterion.condition} <foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," > #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Update_By_Example_Where_Clause" > <where > <foreach collection="example.oredCriteria" item="criteria" separator="or" > <if test="criteria.valid" > <trim prefix="(" suffix=")" prefixOverrides="and" > <foreach collection="criteria.criteria" item="criterion" > <choose > <when test="criterion.noValue" > and ${criterion.condition} </when> <when test="criterion.singleValue" > and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue" > and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue" > and ${criterion.condition} <foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," > #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <!-- 该表中含有的各个列 --> <sql id="Base_Column_List" > id, name, first_char </sql> <!-- SELECT DISTINCT FROM tb_brand WHERE 。。。ORDER BY 。。 --> <select id="selectByExample" resultMap="BaseResultMap" parameterType="com.pinyougou.pojo.TbBrandExample" > select <if test="distinct" > distinct </if> <include refid="Base_Column_List" /> from tb_brand <if test="_parameter != null" > <!-- _parameter? Mybatis的内置参数 代表传入的TbBrandExample对象。也就是把_parameter看作了TbBrandExample的别名--> <include refid="Example_Where_Clause" /> <!-- Example_Where_Clause子句 --> </if> <if test="orderByClause != null" > <!-- orderByClause是TbBrandExample类中的一个属性。 --> order by ${orderByClause} </if> </select> <!-- SELECT id, name, first_char FROM tb_brand WHERE id =。。 --> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" > select <include refid="Base_Column_List" /> from tb_brand where id = #{id,jdbcType=BIGINT} <!-- #{}表示一个占位符。因为parameterType是基本数据类型,所以这个变量名可以随意写。但最好还是写字段名 --> </select> <!-- DELETE FROM tb_brand WHERE id=。。。--> <delete id="deleteByPrimaryKey" parameterType="java.lang.Long" > delete from tb_brand where id = #{id,jdbcType=BIGINT} </delete> <!-- DELETE FROM tb_brand WHERE 。。。使用的是TbBrandExample对象--> <delete id="deleteByExample" parameterType="com.pinyougou.pojo.TbBrandExample" > delete from tb_brand <if test="_parameter != null" > <include refid="Example_Where_Clause" /> </if> </delete> <!-- INSERT INTO tb_brand (id, name, firstChar) VALUES (1 ,"payn" ,null) --> <insert id="insert" parameterType="com.pinyougou.pojo.TbBrand" > insert into tb_brand (id, name, first_char ) values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{firstChar,jdbcType=VARCHAR} ) </insert> <!-- INSERT INTO tb_brand (id, name。。) VALUES (1 ,"payn" 。。。) 使用的TBrand对象--> <insert id="insertSelective" parameterType="com.pinyougou.pojo.TbBrand" > insert into tb_brand <trim prefix="(" suffix=")" suffixOverrides="," > <!-- prefix前缀 suffix后缀 suffixOverrides="," 去掉最后一个“,”--> <if test="id != null" > id, </if> <if test="name != null" > name, </if> <if test="firstChar != null" > first_char, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides="," > <if test="id != null" > #{id,jdbcType=BIGINT}, </if> <if test="name != null" > #{name,jdbcType=VARCHAR}, </if> <if test="firstChar != null" > #{firstChar,jdbcType=VARCHAR}, </if> </trim> </insert> <!-- SELECT count(*) FROM tb_brand WHERE 。。。 使用的是TbBrandExample对象--> <select id="countByExample" parameterType="com.pinyougou.pojo.TbBrandExample" resultType="java.lang.Integer" > select count(*) from tb_brand <if test="_parameter != null" > <include refid="Example_Where_Clause" /> </if> </select> <!-- UPDATE tb_brand set id=。。 ,name=。。 ,first_char=。。 WHERE 。。。 使用的是TbBrand对象和TbBrandExample对象--> <update id="updateByExampleSelective" parameterType="map" > update tb_brand <set > <if test="record.id != null" > id = #{record.id,jdbcType=BIGINT}, </if> <if test="record.name != null" > name = #{record.name,jdbcType=VARCHAR}, </if> <if test="record.firstChar != null" > first_char = #{record.firstChar,jdbcType=VARCHAR}, </if> </set> <if test="_parameter != null" > <include refid="Update_By_Example_Where_Clause" /> </if> </update> <!-- UPDATE tb_brand SET id=xx,name=xx,first_char=xx WHERE。。。 使用的是TbBrand对象(全字段的更新)和TbBrandExample对象 --> <!-- parameterType表示传入的参数的类型 map是什么意思??? 因为方法: int updateByExample(@Param("record") TbBrand record, @Param("example") TbBrandExample example); 使用@param注释的多个参数值也会组装成一个map数据结构,和直接传递map进来没有区别。--> <update id="updateByExample" parameterType="map" > update tb_brand set id = #{record.id,jdbcType=BIGINT}, name = #{record.name,jdbcType=VARCHAR}, first_char = #{record.firstChar,jdbcType=VARCHAR} <if test="_parameter != null" > <include refid="Update_By_Example_Where_Clause" /> </if> </update> <!-- UPDATE tb_brand SET name=。。,first_char=。。WHERE id=xx 使用的是TbBrand对象。更新的是选中的字段。没选中的不会被设置为null。--> <update id="updateByPrimaryKeySelective" parameterType="com.pinyougou.pojo.TbBrand" > update tb_brand <set > <if test="name != null" > name = #{name,jdbcType=VARCHAR}, </if> <if test="firstChar != null" > first_char = #{firstChar,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=BIGINT} </update> <!-- UPDATE tb_brand SET name=xx,first_char=xx WHERE id=xx 使用的是TbBrand对象。更新的是全属性。可能会被更新为null。 --> <update id="updateByPrimaryKey" parameterType="com.pinyougou.pojo.TbBrand" > update tb_brand set name = #{name,jdbcType=VARCHAR}, first_char = #{firstChar,jdbcType=VARCHAR} where id = #{id,jdbcType=BIGINT} </update> <!-- SELECT id,name as text FROM tb_brand; --> <select id="selectOptionList" resultType="java.util.Map"> SELECT id,name as text FROM tb_brand; </select> </mapper>
二、mapper 接口 TbBrandMapper.java
public interface TbBrandMapper { int countByExample(TbBrandExample example); int deleteByExample(TbBrandExample example); int deleteByPrimaryKey(Long id); int insert(TbBrand record); int insertSelective(TbBrand record); List<TbBrand> selectByExample(TbBrandExample example); TbBrand selectByPrimaryKey(Long id); int updateByExampleSelective(@Param("record") TbBrand record, @Param("example") TbBrandExample example); int updateByExample(@Param("record") TbBrand record, @Param("example") TbBrandExample example); int updateByPrimaryKeySelective(TbBrand record); int updateByPrimaryKey(TbBrand record); List<Map> selectOptionList(); }
三、单表简单查询用到的实体类 TbBrand.java TbBrandExample.java
public class TbBrand implements Serializable{ private Long id; private String name; private String firstChar; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } public String getFirstChar() { return firstChar; } public void setFirstChar(String firstChar) { this.firstChar = firstChar == null ? null : firstChar.trim(); } }
public class TbBrandExample { protected String orderByClause; protected boolean distinct; protected List<Criteria> oredCriteria; public TbBrandExample() { oredCriteria = new ArrayList<Criteria>(); } public void setOrderByClause(String orderByClause) { this.orderByClause = orderByClause; } public String getOrderByClause() { return orderByClause; } public void setDistinct(boolean distinct) { this.distinct = distinct; } public boolean isDistinct() { return distinct; } public List<Criteria> getOredCriteria() { return oredCriteria; } public void or(Criteria criteria) { oredCriteria.add(criteria); } public Criteria or() { Criteria criteria = createCriteriaInternal(); oredCriteria.add(criteria); return criteria; } public Criteria createCriteria() { Criteria criteria = createCriteriaInternal(); if (oredCriteria.size() == 0) { oredCriteria.add(criteria); } return criteria; } protected Criteria createCriteriaInternal() { Criteria criteria = new Criteria(); return criteria; } public void clear() { oredCriteria.clear(); orderByClause = null; distinct = false; } protected abstract static class GeneratedCriteria { protected List<Criterion> criteria; protected GeneratedCriteria() { super(); criteria = new ArrayList<Criterion>(); } public boolean isValid() { return criteria.size() > 0; } public List<Criterion> getAllCriteria() { return criteria; } public List<Criterion> getCriteria() { return criteria; } protected void addCriterion(String condition) { if (condition == null) { throw new RuntimeException("Value for condition cannot be null"); } criteria.add(new Criterion(condition)); } protected void addCriterion(String condition, Object value, String property) { if (value == null) { throw new RuntimeException("Value for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value)); } protected void addCriterion(String condition, Object value1, Object value2, String property) { if (value1 == null || value2 == null) { throw new RuntimeException("Between values for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value1, value2)); } public Criteria andIdIsNull() { addCriterion("id is null"); return (Criteria) this; } public Criteria andIdIsNotNull() { addCriterion("id is not null"); return (Criteria) this; } public Criteria andIdEqualTo(Long value) { addCriterion("id =", value, "id"); return (Criteria) this; } public Criteria andIdNotEqualTo(Long value) { addCriterion("id <>", value, "id"); return (Criteria) this; } public Criteria andIdGreaterThan(Long value) { addCriterion("id >", value, "id"); return (Criteria) this; } public Criteria andIdGreaterThanOrEqualTo(Long value) { addCriterion("id >=", value, "id"); return (Criteria) this; } public Criteria andIdLessThan(Long value) { addCriterion("id <", value, "id"); return (Criteria) this; } public Criteria andIdLessThanOrEqualTo(Long value) { addCriterion("id <=", value, "id"); return (Criteria) this; } public Criteria andIdIn(List<Long> values) { addCriterion("id in", values, "id"); return (Criteria) this; } public Criteria andIdNotIn(List<Long> values) { addCriterion("id not in", values, "id"); return (Criteria) this; } public Criteria andIdBetween(Long value1, Long value2) { addCriterion("id between", value1, value2, "id"); return (Criteria) this; } public Criteria andIdNotBetween(Long value1, Long value2) { addCriterion("id not between", value1, value2, "id"); return (Criteria) this; } public Criteria andNameIsNull() { addCriterion("name is null"); return (Criteria) this; } public Criteria andNameIsNotNull() { addCriterion("name is not null"); return (Criteria) this; } public Criteria andNameEqualTo(String value) { addCriterion("name =", value, "name"); return (Criteria) this; } public Criteria andNameNotEqualTo(String value) { addCriterion("name <>", value, "name"); return (Criteria) this; } public Criteria andNameGreaterThan(String value) { addCriterion("name >", value, "name"); return (Criteria) this; } public Criteria andNameGreaterThanOrEqualTo(String value) { addCriterion("name >=", value, "name"); return (Criteria) this; } public Criteria andNameLessThan(String value) { addCriterion("name <", value, "name"); return (Criteria) this; } public Criteria andNameLessThanOrEqualTo(String value) { addCriterion("name <=", value, "name"); return (Criteria) this; } public Criteria andNameLike(String value) { addCriterion("name like", value, "name"); return (Criteria) this; } public Criteria andNameNotLike(String value) { addCriterion("name not like", value, "name"); return (Criteria) this; } public Criteria andNameIn(List<String> values) { addCriterion("name in", values, "name"); return (Criteria) this; } public Criteria andNameNotIn(List<String> values) { addCriterion("name not in", values, "name"); return (Criteria) this; } public Criteria andNameBetween(String value1, String value2) { addCriterion("name between", value1, value2, "name"); return (Criteria) this; } public Criteria andNameNotBetween(String value1, String value2) { addCriterion("name not between", value1, value2, "name"); return (Criteria) this; } public Criteria andFirstCharIsNull() { addCriterion("first_char is null"); return (Criteria) this; } public Criteria andFirstCharIsNotNull() { addCriterion("first_char is not null"); return (Criteria) this; } public Criteria andFirstCharEqualTo(String value) { addCriterion("first_char =", value, "firstChar"); return (Criteria) this; } public Criteria andFirstCharNotEqualTo(String value) { addCriterion("first_char <>", value, "firstChar"); return (Criteria) this; } public Criteria andFirstCharGreaterThan(String value) { addCriterion("first_char >", value, "firstChar"); return (Criteria) this; } public Criteria andFirstCharGreaterThanOrEqualTo(String value) { addCriterion("first_char >=", value, "firstChar"); return (Criteria) this; } public Criteria andFirstCharLessThan(String value) { addCriterion("first_char <", value, "firstChar"); return (Criteria) this; } public Criteria andFirstCharLessThanOrEqualTo(String value) { addCriterion("first_char <=", value, "firstChar"); return (Criteria) this; } public Criteria andFirstCharLike(String value) { addCriterion("first_char like", value, "firstChar"); return (Criteria) this; } public Criteria andFirstCharNotLike(String value) { addCriterion("first_char not like", value, "firstChar"); return (Criteria) this; } public Criteria andFirstCharIn(List<String> values) { addCriterion("first_char in", values, "firstChar"); return (Criteria) this; } public Criteria andFirstCharNotIn(List<String> values) { addCriterion("first_char not in", values, "firstChar"); return (Criteria) this; } public Criteria andFirstCharBetween(String value1, String value2) { addCriterion("first_char between", value1, value2, "firstChar"); return (Criteria) this; } public Criteria andFirstCharNotBetween(String value1, String value2) { addCriterion("first_char not between", value1, value2, "firstChar"); return (Criteria) this; } } public static class Criteria extends GeneratedCriteria { protected Criteria() { super(); } } public static class Criterion { private String condition; private Object value; private Object secondValue; private boolean noValue; private boolean singleValue; private boolean betweenValue; private boolean listValue; private String typeHandler; public String getCondition() { return condition; } public Object getValue() { return value; } public Object getSecondValue() { return secondValue; } public boolean isNoValue() { return noValue; } public boolean isSingleValue() { return singleValue; } public boolean isBetweenValue() { return betweenValue; } public boolean isListValue() { return listValue; } public String getTypeHandler() { return typeHandler; } protected Criterion(String condition) { super(); this.condition = condition; this.typeHandler = null; this.noValue = true; } protected Criterion(String condition, Object value, String typeHandler) { super(); this.condition = condition; this.value = value; this.typeHandler = typeHandler; if (value instanceof List<?>) { this.listValue = true; } else { this.singleValue = true; } } protected Criterion(String condition, Object value) { this(condition, value, null); } protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { super(); this.condition = condition; this.value = value; this.secondValue = secondValue; this.typeHandler = typeHandler; this.betweenValue = true; } protected Criterion(String condition, Object value, Object secondValue) { this(condition, value, secondValue, null); } } }
Mybatis扩展一:<trim>标签
trim标记是一个格式化的标记,可以完成set或者是where标记的功能,如下代码:
select * from user <trim prefix="WHERE" prefixoverride="AND |OR"> <if test="name != null and name.length()>0"> AND name=#{name}</if> <if test="gender != null and gender.length()>0"> AND gender=#{gender}</if> </trim>
假如说name和gender的值都不为null的话打印的SQL为:select * from user where ||||| name = 'xx' and gender = 'xx'
在红色标记的地方是不存在第一个and的,上面两个属性的意思如下:
prefix:前缀
prefixoverride:去掉第一个and或者是or
update user <trim prefix="set" suffix=" where id = #{id}" suffixoverride=","> <if test="name != null and name.length()>0"> name=#{name} , </if> <if test="gender != null and gender.length()>0"> gender=#{gender} , </if> </trim>
假如说name和gender的值都不为null的话打印的SQL为:update user set name='xx' , gender='xx' ||||| where id='x'
在红色标记的地方不存在逗号,而且自动加了一个set前缀和where后缀,上面三个属性的意义如下,其中prefix意义如上:
suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)
suffix:后缀
Mybatis扩展二: @Param parameterType="map"解析
<update id="updateByExample" parameterType="map" > update tb_user set id = #{user.id,jdbcType=INTEGER}, ... <if test="_parameter != null" > <include refid="Update_By_Example_Where_Clause" /> </if> </update>
这里的parameterType=“map”
在mapper接口中:存在如下方法
int updateByExample(@Param("user") User user, @Param("example") UserExample example);
附注:
@Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中 。如下:
public interface Mapper { @Select("select s_id id,s_name name,class_id classid from student where s_name= #{aaaa} and class_id = #{bbbb}") public Student select(@Param("aaaa") String name,@Param("bbbb")int class_id); @Insert...... }
注意:
传入map类型,直接通过#{keyname}就可以引用到键对应的值。使用@param注释的多个参数值也会组装成一个map数据结构,和直接传递map进来没有区别。
不管传递进来的map是否为空,仍然可以使用_parameter。
Mybatis扩展三:内置参数_parameter和_dataBaseId
当mybatis的核心配置文件中配置了databaseIdProvider:
<databaseIdProvider type="DB_VENDOR"> <property name="MySQL" value="mysql"/> <!--//多个数据库提供商配置...--> </databaseIdProvider>
此时在mybatis中的内置参数 _databaseId 中保存了用户指定的对应的数据库厂商标识。
<select id="selectUsrs" databaseId="mysql" resultType="com.heiketu.pojo.Users"> <if test="_databaseId == 'mysql'"> select * from usrs where id = 2 </if> </select>
mybatis的另一个内置参数_parameter 保存了对应传入的对象。
<insert id="insertData" parameterType="com.heiketu.pojo.Users"> insert into usrs values( null, <if test="_parameter != null"> #{_parameter.name}, </if> #{_parameter.age}, #{_parameter.address}, #{_parameter.companyId} ) </insert>
此时_parameter参数就保存了com.heiketu.pojo.Users这个对象。所以可以通用通过 ONGL 表达式从_parameter参数中获取带Users的对应属性值。(也就是将_parameter看做Users的别名)。

浙公网安备 33010602011771号