`
禹爸爸
  • 浏览: 86423 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Mybatis系列之实战篇(中)

阅读更多

Mybatis系列之实战篇(中)

接着《Mybatis系列之实战篇(上)》,我们继续。

 

数据表实体类

Province类

package com.emerson.etao.entity.base.address;

/**
 * 省份实体类
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class Province {
	
	private int provinceId;
	
	private String provinceName;

	public int getProvinceId() {
		return provinceId;
	}

	public void setProvinceId(int provinceId) {
		this.provinceId = provinceId;
	}

	public String getProvinceName() {
		return provinceName;
	}

	public void setProvinceName(String provinceName) {
		this.provinceName = provinceName;
	}

	@Override
	public String toString() {
		return "Province [provinceId=" + provinceId + ", provinceName=" + provinceName + "]";
	}
}

City类

package com.emerson.etao.entity.base.address;

/**
 * 城市实体类
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class City {
	
	private int cityId;
	
	private String cityName;

	public int getCityId() {
		return cityId;
	}

	public void setCityId(int cityId) {
		this.cityId = cityId;
	}

	public String getCityName() {
		return cityName;
	}

	public void setCityName(String cityName) {
		this.cityName = cityName;
	}

	@Override
	public String toString() {
		return "City [cityId=" + cityId + ", cityName=" + cityName + "]";
	}

}

Area类

package com.emerson.etao.entity.base.address;

/**
 * 区域实体类
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class Area {
	
	private int areaId;
	
	private String areaName;

	public int getAreaId() {
		return areaId;
	}

	public void setAreaId(int areaId) {
		this.areaId = areaId;
	}

	public String getAreaName() {
		return areaName;
	}

	public void setAreaName(String areaName) {
		this.areaName = areaName;
	}

	@Override
	public String toString() {
		return "Area [areaId=" + areaId + ", areaName=" + areaName + "]";
	}
}

Purpose类

package com.emerson.etao.entity.base.address;

/**
 * 地址用途实体类
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class Purpose {
	
	public static final int PURPOSE_LEGAL = 1;
	public static final int PURPOSE_BILLTO = 2;
	public static final int PURPOSE_SHIPTO = 3;
	public static final int PURPOSE_DUNNING = 4;
	
	private int purposeId;
	
	private String purposeName;

	public int getPurposeId() {
		return purposeId;
	}

	public void setPurposeId(int purposeId) {
		this.purposeId = purposeId;
	}

	public String getPurposeName() {
		return purposeName;
	}

	public void setPurposeName(String purposeName) {
		this.purposeName = purposeName;
	}

	@Override
	public String toString() {
		return "Purpose [purposeId=" + purposeId + ", purposeName=" + purposeName + "]";
	}

}

Address类

package com.emerson.etao.entity.base.address;

import com.emerson.etao.entity.BaseEntity;

/**
 * 地址实体类
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class Address extends BaseEntity {
	
	private int addressId;
	
	private Province province;
	
	private City city;
	
	private Area area;
	
	private String street;
	
	private String zipCode;
	
	private String contactPerson;
	
	private String tel;
	
	private String fax;
	
	private String cellPhone;
	
	private String email;

	public int getAddressId() {
		return addressId;
	}

	public void setAddressId(int addressId) {
		this.addressId = addressId;
	}

	public Province getProvince() {
		return province;
	}

	public void setProvince(Province province) {
		this.province = province;
	}

	public City getCity() {
		return city;
	}

	public void setCity(City city) {
		this.city = city;
	}

	public Area getArea() {
		return area;
	}

	public void setArea(Area area) {
		this.area = area;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

	public String getZipCode() {
		return zipCode;
	}

	public void setZipCode(String zipCode) {
		this.zipCode = zipCode;
	}

	public String getContactPerson() {
		return contactPerson;
	}

	public void setContactPerson(String contactPerson) {
		this.contactPerson = contactPerson;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public String getFax() {
		return fax;
	}

	public void setFax(String fax) {
		this.fax = fax;
	}

	public String getCellPhone() {
		return cellPhone;
	}

	public void setCellPhone(String cellPhone) {
		this.cellPhone = cellPhone;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
	
	public String toDisplayString() {
		String result = province.getProvinceName() + ", " + city.getCityName() + ", " + area.getAreaName() + ", " +
	     this.street + ", " + this.zipCode + ", " + this.contactPerson;
		if ((this.tel != null) && !("".equals(this.tel))) {
			result += ", " + this.tel;
		}
		else if ((this.cellPhone != null) && !("".equals(this.cellPhone))) {
			result += ", " + this.cellPhone;
		}
		return result;
	}

	@Override
	public String toString() {
		return "Address [addressId=" + addressId + ", province=" + province + ", city=" + city + ", area=" + area
				+ ", street=" + street + ", zipCode=" + zipCode + ", contactPerson=" + contactPerson + ", tel=" + tel
				+ ", fax=" + fax + ", cellPhone=" + cellPhone + ", email=" + email + ", isValid=" + isValid
				+ ", createdTime=" + createdTime + ", updateTime=" + updateTime + "]";
	}
	

}

Party类

package com.emerson.etao.entity.base.customer;

import com.emerson.etao.entity.BaseEntity;

/**
 * 客户Party实体类
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class Party extends BaseEntity {
	
	private int partyId;

	private String partyName;

	private String country;

	private String area;

	public int getPartyId() {
		return partyId;
	}

	public void setPartyId(int partyId) {
		this.partyId = partyId;
	}

	public String getPartyName() {
		return partyName;
	}

	public void setPartyName(String partyName) {
		this.partyName = partyName;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public String getArea() {
		return area;
	}

	public void setArea(String area) {
		this.area = area;
	}

	@Override
	public String toString() {
		return "Party [partyId=" + partyId + ", partyName=" + partyName + ", country=" + country + ", area=" + area
				+ ", isValid=" + isValid + ", createdTime=" + createdTime + ", updateTime=" + updateTime + "]";
	}
}

Code类

package com.emerson.etao.entity.base.customer;

import com.emerson.etao.entity.BaseEntity;
import com.emerson.etao.entity.base.Plant;

/**
 * 客户代码实体类
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class Code extends BaseEntity {
	
	private int codeId;
	
	private String customerCode;
	
	private Party party;
	
	private Plant plant;
	
	public int getCodeId() {
		return codeId;
	}

	public void setCodeId(int codeId) {
		this.codeId = codeId;
	}

	public String getCustomerCode() {
		return customerCode;
	}

	public void setCustomerCode(String customerCode) {
		this.customerCode = customerCode;
	}

	public Plant getPlant() {
		return plant;
	}

	public void setPlant(Plant plant) {
		this.plant = plant;
	}

	public Party getParty() {
		return party;
	}

	public void setParty(Party party) {
		this.party = party;
	}

	@Override
	public String toString() {
		return "Code [codeId=" + codeId + ", customerCode=" + customerCode + ", party=" + party + ", plant=" + plant + ", isValid=" + isValid + ", createdTime=" + createdTime
				+ ", updateTime=" + updateTime + "]";
	}
}

Location类

package com.emerson.etao.entity.base.customer;

import com.emerson.etao.entity.BaseEntity;
import com.emerson.etao.entity.base.address.Address;
import com.emerson.etao.entity.base.address.Purpose;

/**
 * 客户位置实体类
 * 
 * 地址 + 用途,构成客户位置
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class Location extends BaseEntity {

	private int locationId;
	
	private int codeId;

	private Address address;

	private Purpose purpose;

	public int getLocationId() {
		return locationId;
	}

	public void setLocationId(int locationId) {
		this.locationId = locationId;
	}

	public int getCodeId() {
		return codeId;
	}

	public void setCodeId(int codeId) {
		this.codeId = codeId;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public Purpose getPurpose() {
		return purpose;
	}

	public void setPurpose(Purpose purpose) {
		this.purpose = purpose;
	}
	
	public String toDisplayString() {
		return this.purpose.getPurposeName() + ": " + this.address.toDisplayString();
	}

	@Override
	public String toString() {
		return "Location [locationId=" + locationId + ", address=" + address + ", purpose=" + purpose + "]";
	}

}

以上这些都准备好了,下面可以开始着手写Mybatis映射文件了。我们自底向上,从地址开始写起。

 

Address类Dao接口、Service接口、映射文件及单元测试

Dao接口

Address作为基础类,不仅要实现基类(参见《Mybatis系列之实战篇(上)》中“Mybatisy接口及映射文件”)中约定的方法,还需要额外定义了三个方法,分别用于获取省、市、区的列表。

package com.emerson.etao.dao.base.address;

import java.util.List;

import com.emerson.etao.dao.IBaseDao;
import com.emerson.etao.entity.base.address.Address;
import com.emerson.etao.entity.base.address.Area;
import com.emerson.etao.entity.base.address.City;
import com.emerson.etao.entity.base.address.Province;

/**
 * 地址DAO接口
 * 
 * @author Chris Mao(Zibing)
 *
 */
public interface IAddressDao extends IBaseDao<Address> {
	
	/**
	 * 获取省份列表
	 * 
	 * @return
	 */
	public List<Province> getProvinceList();
	
	/**
	 * 获取指定省份的城市列表
	 * 
	 * @param provinceId
	 * @return
	 */
	public List<City> getCityList(int provinceId);
	
	/**
	 * 获取指定城市的地区列表
	 * 
	 * @param cityId
	 * @return
	 */
	public List<Area> getAreaList(int cityId);

}

映射文件

由于我们使用了接口式编程,所以映射文件中的名称空间名称必须和我们定义的接口全限定名一致! 

<?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.emerson.etao.dao.base.address.IAddressDao">
	<sql id="selectColumns">
		address_id, province_id, province_name, city_id, city_name,
		area_id, street, zip_code, contact_person, tel, fax, cell_phone,
		email, is_valid, created_time, update_time
	</sql>

	<sql id="insertColumns">
		province_id, city_id, area_id, street, zip_code,
		contact_person, tel, fax, cell_phone, email, is_valid,
		created_time
	</sql>

	<!-- 省份映射关系 -->
	<resultMap id="provinceResultMap" type="com.emerson.etao.entity.base.address.Province">
		<id property="provinceId" column="province_id" />
		<result property="provinceName" column="province_name" />
	</resultMap>

	<!-- 城市映射关系 -->
    <resultMap id="cityResultMap" type="com.emerson.etao.entity.base.address.City">
		<id property="cityId" column="city_id" />
		<result property="cityName" column="city_name" />
	</resultMap>

	<!-- 地区映射关系 -->
    <resultMap id="areaResultMap" type="com.emerson.etao.entity.base.address.Area">
		<id property="areaId" column="area_id" />
		<result property="areaName" column="area_name" />
	</resultMap>

	<!-- 地址映射关系 -->
    <resultMap id="addressResultMap" type="com.emerson.etao.entity.base.address.Address">
		<id property="addressId" column="address_id" />
		<result property="street" column="street" />
		<result property="zipCode" column="zip_code" />
		<result property="contactPerson" column="contact_person" />
		<result property="fax" column="fax" />
		<result property="tel" column="tel" />
		<result property="cellPhone" column="cell_phone" />
		<result property="email" column="email" />
		<result property="isValid" column="is_valid" />
		<result property="createdTime" column="created_time" />
		<result property="updateTime" column="update_time" />
		<association property="province" column="province_id"
			resultMap="provinceResultMap" />
		<association property="city" column="city_id" resultMap="cityResultMap" />
		<association property="area" column="area_id" resultMap="areaResultMap" />
	</resultMap>

	<!-- 地址用途映射关系 -->
    <resultMap id="purposeResultMap" type="com.emerson.etao.entity.base.address.Purpose">
		<id property="purposeId" column="purpose_id" />
		<result property="purposeName" column="purpose_name" />
	</resultMap>

	<!-- 按Id值查询地址 -->
    <select id="getById" parameterType="int" resultMap="addressResultMap">
		SELECT
		<include refid="selectColumns"></include>
		FROM vw_address WHERE address_id = #{id}
	</select>

	<!-- 获取所有地址 -->
    <select id="getAll" resultMap="addressResultMap">
		SELECT
		<include refid="selectColumns"></include>
		FROM vw_address ORDER BY province_id, city_id, area_id
	</select>

	<!-- 查询省份列表 -->
	<select id="getProvinceList" resultType="com.emerson.etao.entity.base.address.Province">
		SELECT province_id,
		province_name, is_valid, created_time, update_time FROM
		addr_province
		ORDER BY province_name
	</select>

	<!-- 查询指定省份下的城市列表 -->
	<select id="getCityList" parameterType="int"
		resultType="com.emerson.etao.entity.base.address.City">
		SELECT city_id, city_name, is_valid, created_time,
		update_time FROM
		addr_city WHERE province_id = #{id} ORDER BY city_name
	</select>

	<!-- 查询指定城市下的地区列表 -->
	<select id="getAreaList" parameterType="int"
		resultType="com.emerson.etao.entity.base.address.Area">
		SELECT area_id, area_name, is_valid, created_time,
		update_time FROM
		addr_area WHERE city_id = #{id} ORDER BY area_name
	</select>

	<!-- 
	  查询符合查询条年的地址,可以按
	  address_id, province_id, province_name, city_id, city_name, area_id, 
	  area_name, street, zip_code, contact_person, tel, fax, cell_phone, email
	  进行查询
	 -->
    <select id="find" parameterType="com.emerson.etao.entity.base.address.Address"
		resultMap="addressResultMap">
		SELECT
		<include refid="selectColumns"></include>
		FROM vw_address
		<where>
			<if test="addressId != 0">AND address_id = #{addressId}</if>
			<if test="province != null and province.provinceId != 0">AND province_id = #{province.provinceId}</if>
			<if test="province != null and province.provinceName != null">AND province_name LIKE CONCAT('%',
				#{province.provinceName}, '%')</if>
			<if test="city != null and city.cityId != 0">AND city_id = #{city.cityId}</if>
			<if test="city != null and city.cityName != null">AND city_name LIKE CONCAT('%', #{city.cityName}, '%')
			</if>
			<if test="area != null and area.areaId != 0">AND area_id = #{area.areaId}</if>
			<if test="area != null and area.areaName != null">AND area_name LIKE CONCAT('%', #{area.areaName}, '%')
			</if>
			<if test="street != null">AND street LIKE CONCAT('%', #{street}, '%')</if>
			<if test="zipCode != null">AND zip_code LIKE CONCAT('%', #{zipCode}, '%')</if>
			<if test="contactPerson != null">AND contact_person LIKE CONCAT('%', #{contactPerson},
				'%')</if>
			<if test="tel != null">AND tel LIKE CONCAT('%', #{tel}, '%')</if>
			<if test="fax != null">AND fax LIKE CONCAT('%', #{fax}, '%')</if>
			<if test="cellPhone != null">AND cell_phone LIKE CONCAT('%', #{cellPhone}, '%')</if>
			<if test="email != null">AND email LIKE CONCAT('%', #{email}, '%')</if>
		</where>
		ORDER BY province_id, city_id, area_id
	</select>

	<!-- 插入数据并返回主键值,注意,这里的KeyProperty应该是Java类里的属性名称,而非数据表中的字段名 -->
	<insert id="insert" parameterType="com.emerson.etao.entity.base.address.Address"
		useGeneratedKeys="true" keyProperty="addressId">
		INSERT INTO address(
		<include refid="insertColumns"></include>
		)
		VALUES(#{province.provinceId}, #{city.cityId}, #{area.areaId},
		#{street}, #{zipCode}, #{contactPerson}, #{tel}, #{fax},
		#{cellPhone},
		#{email}, #{isValid}, #{createdTime})
	</insert>

	<!-- 批量新增 -->
	<insert id="batchInsert" parameterType="java.util.List">
		INSERT INTO address(
		<include refid="insertColumns"></include>
		) VALUES
		<foreach collection="list" item="addr" separator=",">
			(#{addr.province.provinceId}, #{addr.city.cityId},
			#{addr.area.areaId}, #{addr.street}, #{addr.zip_code},
			#{addr.contactPerson}, #{addr.tel}, #{addr.fax}, #{addr.cellPhone},
			#{addr.email}, #{addr.isValid}, #{addr.createdTime})
		</foreach>
	</insert>

	<!-- 更新数据 -->
	<update id="update" parameterType="com.emerson.etao.entity.base.address.Address">
		UPDATE address
		<set>
			<if test="province != null and province.provinceId != 0">province_id = #{province.provinceId},</if>
			<if test="city != null and city.cityId != 0">city_id = #{city.cityId},</if>
			<if test="area != null and area.areaId != 0">area_id = #{area.areaId},</if>
			<if test="street != null">street = #{street},</if>
			<if test="zipCode != null">zip_code = #{zipCode},</if>
			<if test="contactPerson != null">contact_person = #{contactPerson},</if>
			<if test="tel != null">tel = #{tel},</if>
			<if test="fax != null">fax = #{fax},</if>
			<if test="cellPhone != null">cell_phone = #{cellPhone},</if>
			<if test="email != null">email = #{email}</if>
		</set>
		WHERE address_id = #{addressId}
	</update>

	<!-- 根据传入的Id值,删除单条记录 -->
	<delete id="delete" parameterType="int">
		UPDATE address SET is_valid =
		0 WHERE address_id = #{id}
	</delete>

	<!-- 根据传入的Id值列表,删除多条记录 -->
	<delete id="batchDelete" parameterType="java.util.List">
		UPDATE address SET is_valid = 0 WHERE address_id in
		<foreach collection="list" item="item" index="index" open="("
			close=")" separator=",">
			#{item}
		</foreach>
	</delete>
</mapper>
这里着重讲解一下id为find的select元素的写法。这是一个查询方法,把查询条件封装成一个实体类对象,然后根据其属性值,动态生成SQL查询语句。Address对象中又嵌套有Province / City / Arae三个子对象,所以要创建查询语句时,在引用其属性值之前,一定要判断其是否为null值,否则有可能会得到空引用的错误
	<!-- 
	  查询符合查询条年的地址,可以按
	  address_id, province_id, province_name, city_id, city_name, area_id, 
	  area_name, street, zip_code, contact_person, tel, fax, cell_phone, email
	  进行查询
	 -->
    <select id="find" parameterType="com.emerson.etao.entity.base.address.Address"
		resultMap="addressResultMap">
		SELECT
		<include refid="selectColumns"></include>
		FROM vw_address
		<where>
			<if test="addressId != 0">AND address_id = #{addressId}</if>
			<if test="province != null and province.provinceId != 0">AND province_id = #{province.provinceId}</if>
			<if test="province != null and province.provinceName != null">AND province_name LIKE CONCAT('%',
				#{province.provinceName}, '%')</if>
			<if test="city != null and city.cityId != 0">AND city_id = #{city.cityId}</if>
			<if test="city != null and city.cityName != null">AND city_name LIKE CONCAT('%', #{city.cityName}, '%')
			</if>
			<if test="area != null and area.areaId != 0">AND area_id = #{area.areaId}</if>
			<if test="area != null and area.areaName != null">AND area_name LIKE CONCAT('%', #{area.areaName}, '%')
			</if>
			<if test="street != null">AND street LIKE CONCAT('%', #{street}, '%')</if>
			<if test="zipCode != null">AND zip_code LIKE CONCAT('%', #{zipCode}, '%')</if>
			<if test="contactPerson != null">AND contact_person LIKE CONCAT('%', #{contactPerson},
				'%')</if>
			<if test="tel != null">AND tel LIKE CONCAT('%', #{tel}, '%')</if>
			<if test="fax != null">AND fax LIKE CONCAT('%', #{fax}, '%')</if>
			<if test="cellPhone != null">AND cell_phone LIKE CONCAT('%', #{cellPhone}, '%')</if>
			<if test="email != null">AND email LIKE CONCAT('%', #{email}, '%')</if>
		</where>
		ORDER BY province_id, city_id, area_id
	</select>

在映射文件中除了用到了select / insert / update / delete 元素,还使用到了创建动态SQL的where / set / if元素,以及foreach,小伙伴可以慢慢体会这些元素的使用方法。

 

Service接口及实现

接口定义。

package com.emerson.etao.service.base.address;

import java.util.List;

import com.emerson.etao.entity.base.address.Address;
import com.emerson.etao.entity.base.address.Area;
import com.emerson.etao.entity.base.address.City;
import com.emerson.etao.entity.base.address.Province;
import com.emerson.etao.service.IBaseService;

/**
 * 客户地址服务层接口
 * 
 * @author Chris Mao(Zibing)
 *
 */
public interface IAddressService extends IBaseService<Address> {
	
	/**
	 * 获取省份列表
	 * 
	 * @return
	 */
	public List<Province> getProvinceList();
	
	/**
	 * 获取指定省份的城市列表
	 * 
	 * @param provinceId
	 * @return
	 */
	public List<City> getCityList(int provinceId);
	
	/**
	 * 获取指定城市的地区列表
	 * 
	 * @param cityId
	 * @return
	 */
	public List<Area> getAreaList(int cityId);

}

接口实现,这里需要在接口实现类的定义处使用Service注解将其定义为一个J2EE组件。

package com.emerson.etao.service.impl.base.address;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.emerson.etao.dao.IBaseDao;
import com.emerson.etao.dao.base.address.IAddressDao;
import com.emerson.etao.entity.base.address.Address;
import com.emerson.etao.entity.base.address.Area;
import com.emerson.etao.entity.base.address.City;
import com.emerson.etao.entity.base.address.Province;
import com.emerson.etao.service.base.address.IAddressService;
import com.emerson.etao.service.impl.BaseServiceImpl;

/**
 * 地址服务接口
 * 
 * @author Chris Mao(Zibing)
 *
 */
@Service("addressService")
public class AddressServiceImpl extends BaseServiceImpl<Address> implements IAddressService {

	@Resource
	private IAddressDao dao;

	@Override
	protected IBaseDao<Address> getBaseDao() {
		return this.dao;
	}
	
	@Override
	public List<Province> getProvinceList() {
		return this.dao.getProvinceList();
	}
	
	@Override
	public List<City> getCityList(int provinceId) {
		return this.dao.getCityList(provinceId);
	}
	
	@Override
	public List<Area> getAreaList(int cityId) {
		return this.dao.getAreaList(cityId);
	}

}

单元测试

这些都写好之后,就可以对我们写的代码进行单元测试了。我们一定要培养自己有写单元测试的习惯,这样不仅可以确保自己的代码质量,即便在将来我们对代码进行重构或是增加功能时,这些测试代码仍可以复用,确保我们不会因为重构或是增加新的功能引入新的错误。通过了单元测试并不能说明我们的程序完全没有作何问题。单元测试只能确保我们的程序代码没有技术错误,无法保证没有业务错误。所以后继我们还会对程序进行功能测试,来暴露出程序上的功能错误。

package com.emerson.etao.service.address;

import static org.junit.Assert.*;

import java.util.List;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.emerson.etao.entity.base.address.*;
import com.emerson.etao.service.base.address.IAddressService;

/**
 * 地址服务测试类
 * 
 * @author Chris Mao(Zibing)
 *
 */
public class AddressServiceTest {

	private static IAddressService addressService;
	
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		ApplicationContext ac = new ClassPathXmlApplicationContext("root-context-test.xml");
		addressService = (IAddressService) ac.getBean("addressService");
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		addressService = null;
	}

	@Test
	public void testGetById() {
		System.out.println("testGetById start...");
		Address address = addressService.getById(1);
		assertNotNull(address);
		System.out.println("testGetById end...");
	}

	@Test
	public void testGetAll() {
		System.out.println("testGetAll start...");
		List<Address> list = addressService.getAll(0);
		assertNotNull(list);
		System.out.println("testGetAll end...");
	}
	
	@Test
	public void testFind() {
		System.out.println("testFind start...");
		Address address = new Address();
		address.setZipCode("433");
		List<Address> list = addressService.find(address);
		assertEquals(1, list.size());
		
		address.setZipCode(null);
		address.setProvince(new Province());
		address.getProvince().setProvinceName("上海");
		list = addressService.find(address);
		assertEquals(1, list.size());
		System.out.println("testFind end...");
	}

	@Test
	public void testInsert() {
		System.out.println("testInsert start...");
		Address address = new Address();
		Province province = new Province();
		City city = new City();
		Area area = new Area();
		province.setProvinceId(2);
		city.setCityId(2);
		area.setAreaId(26);
		address.setProvince(province);
		address.setCity(city);
		address.setArea(area);
		address.setStreet("工艺品公司进出口仓库8号库军工路1300");
		address.setZipCode("200433");
		address.setContactPerson("陈伟民");
		address.setTel("021-65797887");
		address.setFax(null);
		address.setCellPhone(null);
		addressService.insert(address);
		System.out.println("testInsert end...");
	}
	
	@Test
	public void testBatchInsert() {
		System.out.println("testBatchInsert start...");
		System.out.println("testBatchInsert end...");
	}

	@Test
	public void testUpdate() {
		System.out.println("testUpdate start...");
		Address address = addressService.getById(1);
		address.setEmail("chris.mao.zb@163.com");
		int effectedRows = addressService.update(address);
		assertEquals(1, effectedRows);
		System.out.println("testUpdate end...");
	}

	@Test
	public void testDelete() {
		System.out.println("testDelete start...");
		int effectedRows = addressService.delete(1);
		assertEquals(1, effectedRows);
		System.out.println("testDelete end...");
	}
	
	@Test
	public void testBatchDelete() {
		System.out.println("testBatchDelete start...");
		System.out.println("testBatchDelete end...");
	}

	@Test
	public void testGetProvinceList() {
		System.out.println("testGetProvinceList start...");
		List<Province> list = addressService.getProvinceList();
		assertEquals(34, list.size());
		System.out.println("testGetProvinceList end...");
	}

	@Test
	public void testGetCityList() {
		System.out.println("testGetCityList start...");
		List<City> list = addressService.getCityList(12); // Jiangsu
		assertEquals(13, list.size());
		System.out.println("testGetCityList end...");
	}

	@Test
	public void testGetAreaList() {
		System.out.println("testGetAreaList start...");
		List<Area> list = addressService.getAreaList(113); // Suzhou
		assertEquals(13, list.size());
		System.out.println("testGetAreaList end...");
	}
}

 

Plant / Party / Code其实现步骤和Address类一样,也是要经过定义Dao接口、编写映射文件、定义服务层接口并实现其功能,以及单元测试这样四步。本文重点放在了映射文件的编写上,所以,这里就仅贴出其他类的映射文件内容,有兴趣的小伙伴也可以试着自己完成接口部分和测试部分的编写。

 

Plant映射文件

<?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.emerson.etao.dao.base.IPlantDao">
    <sql id="selectColumns">
        plant_id, plant_code, plant_name, is_valid, created_time, update_time
    </sql>

    <sql id="insertColumns">
        plant_code, plant_name, is_valid, created_time
    </sql>

    <select id="getById" parameterType="int" resultType="com.emerson.etao.entity.base.Plant">
        SELECT
        <include refid="selectColumns"></include>
        FROM plant WHERE plant_id = #{id}
    </select>

    <select id="getAll" resultType="com.emerson.etao.entity.base.Plant">
        SELECT
        <include refid="selectColumns"></include>
        FROM plant ORDER BY plant_id
    </select>

    <!-- 插入数据并返回主键值,注意,这里的KeyProperty应该是Java类里的属性名称,而非数据表中的字段名 -->
    <insert id="insert" parameterType="com.emerson.etao.entity.base.Plant" useGeneratedKeys="true" keyProperty="plantId">
        INSERT INTO plant(<include refid="insertColumns"></include>)
        VALUES(#{plantCode}, #{plantName}, #{isValid}, #{createdTime})
    </insert>

    <!-- 批量新增 -->
    <insert id="batchInsert" parameterType="java.util.List">
        INSERT INTO plant(<include refid="insertColumns"></include>) VALUES
        <foreach collection="list" item="p" separator=",">
            (#{p.plantCode}, #{p.plantName}, #{p.isValid}, #{p.createdTime})
        </foreach>
    </insert>

    <!-- 更新数据 -->
    <update id="update" parameterType="com.emerson.etao.entity.base.Plant">
        UPDATE plant
        <set>
        </set>
        WHERE plant_id = #{plantId}
    </update>

    <!-- 根据传入的Id值,删除单条记录 -->
    <delete id="delete" parameterType="int">
        UPDATE plant SET is_valid = 0 WHERE plant_id = #{id}
    </delete>

    <!-- 根据传入的Id值列表,删除多条记录 -->
    <delete id="batchDelete" parameterType="java.util.List">
        UPDATE plant SET is_valid = 0 WHERE plant_id in
        <foreach collection="list" item="item" index="index" open="("
            close=")" separator=",">
            #{item}
        </foreach>
    </delete>
</mapper>

Party映射文件

<?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.emerson.etao.dao.base.customer.IPartyDao">
	<sql id="selectColumns">
		party_id, party_name, country, area, is_valid,
		created_time, update_time
	</sql>

	<sql id="insertColumns">
		party_name, country, area, is_valid, created_time
	</sql>

	<select id="getById" parameterType="int"
		resultType="com.emerson.etao.entity.base.customer.Party">
		SELECT
		<include refid="selectColumns"></include>
		FROM customer_party WHERE party_id = #{id}
	</select>

	<select id="getAll" resultType="com.emerson.etao.entity.base.customer.Party">
		SELECT
		<include refid="selectColumns"></include>
		FROM customer_party ORDER BY party_id
	</select>

	<select id="find" parameterType="com.emerson.etao.entity.base.customer.Party"
		resultType="com.emerson.etao.entity.base.customer.Party">
		SELECT
		<include refid="selectColumns"></include>
		FROM customer_party
		<where>
			<if test="partyName != null">party_name LIKE CONCAT('%', #{partyName}, '%')</if>
			<if test="country != null">OR country LIKE CONCAT('%', #{country}, '%')</if>
			<if test="area != null">OR area LIKE CONCAT('%', #{area}, '%')</if>
			<if test="isValid != null">AND is_valid = #{isValid}</if>
		</where>
	</select>

	<select id="getAllCode" parameterType="int"
		resultMap="com.emerson.etao.dao.base.customer.ICodeDao.codeResultMap">
	    SELECT <include refid="com.emerson.etao.dao.base.customer.ICodeDao.selectColumns"></include>
	    FROM vw_customer_code WHERE party_id = #{id}
        ORDER BY party_id, customer_code
	</select>

	<!-- 插入数据并返回主键值,注意,这里的KeyProperty应该是Java类里的属性名称,而非数据表中的字段名 -->
	<insert id="insert" parameterType="com.emerson.etao.entity.base.customer.Party"
		useGeneratedKeys="true" keyProperty="partyId">
		INSERT INTO customer_party(
		<include refid="insertColumns"></include>
		)
		VALUES(#{partyName}, #{country}, #{area}, #{isValid}, #{createdTime})
	</insert>

	<!-- 批量新增 -->
	<insert id="batchInsert" parameterType="java.util.List">
		INSERT INTO customer_party(
		<include refid="insertColumns"></include>
		) VALUES
		<foreach collection="list" item="party" separator=",">
			(#{party.partyName}, #{party.country}, #{party.area},
			#{party.isValid}, #{party.createdTime})
		</foreach>
	</insert>

	<!-- 更新数据 -->
	<update id="update" parameterType="com.emerson.etao.entity.base.customer.Party">
		UPDATE customer_party
		<set>
			<if test="partyName != null">party_name = #{partyName},</if>
			<if test="country != null">country = #{country},</if>
			<if test="area != null">area = #{area},</if>
			<if test="isValid != null">is_valid = #{isValid},</if>
		</set>
		WHERE party_id = #{partyId}
	</update>

	<!-- 根据传入的Id值,删除单条记录 -->
	<delete id="delete" parameterType="int">
		UPDATE customer_party SET
		is_valid = 0
		WHERE party_id = #{id}
	</delete>

	<!-- 根据传入的Id值列表,删除多条记录 -->
	<delete id="batchDelete" parameterType="java.util.List">
		UPDATE customer_party SET is_valid = 0 WHERE party_id in
		<foreach collection="list" item="item" index="index" open="("
			close=")" separator=",">
			#{item}
		</foreach>
	</delete>
</mapper>

Code映射文件

<?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.emerson.etao.dao.base.customer.ICodeDao">
	<sql id="selectColumns">
		code_id ,customer_code, plant_id, party_id,
		is_valid, created_time, update_time,
		plant_code, plant_name,
		plant_is_valid, plant_created_time,
		plant_update_time,
		party_name, country, area, party_is_valid,
		party_created_time, party_update_time
	</sql>

	<sql id="insertColumns">
		customer_code, plant_id, party_id, is_valid, created_time
	</sql>

	<!-- 工厂映射关系 -->
    <resultMap id="plantResultMap" type="com.emerson.etao.entity.base.Plant">
		<id property="plantId" column="plant_id" />
		<result property="plantCode" column="plant_code" />
		<result property="plantName" column="plant_name" />
		<result property="isValid" column="plant_is_valid" />
		<result property="createdTime" column="plant_created_time" />
		<result property="updateTime" column="plant_update_time" />
	</resultMap>

	<!-- 客户Party映射关系 -->
    <resultMap id="partyResultMap" type="com.emerson.etao.entity.base.customer.Party">
		<id property="partyId" column="party_id" />
		<result property="partyName" column="party_name" />
		<result property="country" column="country" />
		<result property="area" column="area" />
		<result property="isValid" column="party_is_valid" />
		<result property="createdTime" column="party_created_time" />
		<result property="updateTime" column="party_update_time" />
	</resultMap>

	<!-- 客户代码映射关系 -->
    <resultMap id="codeResultMap" type="com.emerson.etao.entity.base.customer.Code">
		<id property="codeId" column="code_id" />
		<result property="customerCode" column="customer_code" />
		<result property="isValid" column="is_valid" />
		<result property="createdTime" column="created_time" />
		<result property="updateTime" column="update_time" />
		<association property="party" column="party_id" resultMap="partyResultMap"></association>
		<association property="plant" column="plant_id" resultMap="plantResultMap"></association>
	</resultMap>

	<!-- 客户地点映射关系,包含地址和用途 -->
    <resultMap id="locationResultMap"
		type="com.emerson.etao.entity.base.customer.Location">
		<id property="locationId" column="location_id" />
		<result property="codeId" column="code_id" />
		<result property="isValid" column="is_valid" />
		<result property="createdTime" column="created_time" />
		<result property="updateTime" column="update_time" />
		<association property="address" column="address_id"
			resultMap="com.emerson.etao.dao.base.address.IAddressDao.addressResultMap" />
		<association property="purpose" column="purpose_id"
			resultMap="com.emerson.etao.dao.base.address.IAddressDao.purposeResultMap" />
	</resultMap>

	<!-- 按Id值查询客户代码 -->
    <select id="getById" parameterType="int" resultMap="codeResultMap">
		SELECT
		<include refid="selectColumns"></include>
		FROM vw_customer_code WHERE code_id = #{id}
	</select>

	<!-- 获取所有客户代码 -->
    <select id="getAll" resultMap="codeResultMap">
		SELECT
		<include refid="selectColumns"></include>
		FROM vw_customer_code ORDER BY customer_code
	</select>

	<!-- 
	  查询符合条件的客户代码,可以按
	  customer_code, plant_id, plant_code, party_id, party_name,
	  deliverty_type_id, shippint_term_id, payment_term_id, rebate_allowed,
	  credit_allowed, sp_allowed
	  进行查询
	 -->
    <select id="find" parameterType="com.emerson.etao.entity.base.customer.Code"
		resultMap="codeResultMap">
		SELECT
		<include refid="selectColumns"></include>
		FROM vw_customer_code
		<where>
			<if test="customerCode != null">customer_code LIKE CONCAT('%', #{customerCode}, '%')</if>
			<if test="plant != null and plant.plantId != 0">AND plant_id = #{plant.plantId}</if>
			<if test="plant != null and plant.plantCode != null">AND plant_code LIKE CONCAT('%', #{plant.plantCode}, '%')
			</if>
			<if test="party != null and party.partyId != 0">AND party_id = #{party.partyId}</if>
			<if test="party != null and party.partyName != null">AND party_name LIKE CONCAT('%', #{party.partyName}, '%')
			</if>
		</where>
		ORDER BY customer_code
	</select>

	<!-- 
	  查询符合条件的所有地点记录,可以按
	  location_id, code_id, purpose_id, purpose_name
	  进行查询
	-->
	<select id="findLocation" parameterType="com.emerson.etao.entity.base.customer.Location"
		resultMap="locationResultMap">
		SELECT location_id, address_id, code_id, purpose_id, purpose_name,
        province_id, province_name, city_id, city_name, area_id, area_name,
        street, zip_code, contact_person, tel, fax, cell_phone, email,
        is_valid, created_time, update_time
        FROM vw_customer_location
        <where>
            <if test="locationId != 0">AND location_id = #{locationId}</if>
            <if test="codeId != 0">AND code_id = #{codeId}</if>
            <if test="purpose != null and purpose.purposeId != 0">AND purpose_id = #{purpose.purposeId}</if>
            <if test="purpose != null and purpose.purposeName != null">AND purpose_name LIKE CONCAT('%', #{purpose.purposeName}, '%')</if>
        </where>
	</select>

	<!-- 插入数据并返回主键值,注意,这里的KeyProperty应该是Java类里的属性名称,而非数据表中的字段名 -->
	<insert id="insert" parameterType="com.emerson.etao.entity.base.customer.Code"
		useGeneratedKeys="true" keyProperty="codeId">
		INSERT INTO customer_code(
		<include refid="insertColumns"></include>
		)
		VALUES(#{customerCode}, #{plant.plantId}, #{party.partyId},
		#{isValid}, #{createdTime})
	</insert>

	<!-- 批量新增 -->
	<insert id="batchInsert" parameterType="java.util.List">
		INSERT INTO customer_code(
		<include refid="insertColumns"></include>
		) VALUES
		<foreach collection="list" item="c" separator=",">
			(#{c.customerCode}, #{c.plant.plantId}, #{c.party.partyId},
			#{c.isValid}, #{c.createdTime})
		</foreach>
	</insert>

	<!-- 
	  创建客户地点
	  需要先创建或是选取一个地址,再选择一个用途,并与客户代码进行绑定
	-->
    <insert id="createLocation" parameterType="com.emerson.etao.entity.base.customer.Location"
		useGeneratedKeys="true" keyProperty="locationId">
		INSERT INTO customer_location
		(code_id, address_id, purpose_id, is_valid, created_time)
		VALUES(#{codeId}, #{address.addressId}, #{purpose.purposeId},
		#{isValid}, #{createdTime})
	</insert>

	<!-- 更新数据 -->
	<update id="update" parameterType="com.emerson.etao.entity.base.customer.Code">
		UPDATE customer_code
		<set>
			<if test="plant != null and plant.plantId != 0">plant_id = #{plant.plantId},</if>
			<if test="party != null and party.partyId != 0">party_id = #{party.partyId},</if>
		</set>
		WHERE code_id = #{codeId}
	</update>

	<!-- 根据传入的Id值,删除单条记录 -->
	<delete id="delete" parameterType="int">
		UPDATE customer_code SET
		is_valid = 0 WHERE code_id = #{id}
	</delete>

	<!-- 根据传入的Id值列表,删除多条记录 -->
	<delete id="batchDelete" parameterType="java.util.List">
		UPDATE customer_code SET is_valid = 0 WHERE id in
		<foreach collection="list" item="item" index="index" open="("
			close=")" separator=",">
			#{item}
		</foreach>
	</delete>

	<!-- 删除客户地点 -->
    <delete id="removeLocation" parameterType="int">
		DELETE FROM customer_location WHERE location_id = #{id}
	</delete>
</mapper>

至此,这个示例的代码部分已全部讲解完毕。在《Mybatis系列这实战篇(下)》中,我会对开发中需要注意的问题点进行总结。

 

附录

Mybatis系列(一)入门

Mybatis系列(二)配置

Mybatis系列(三)简单示例

Mybatis系列(四)映射文件

ybatis系列(五)动态SQL

Mybatis系列(六)接口式编程

Mybatis系列(七)关联映射

Mybatis系列(八)集合映射

Mybatis系列(九)Spring & Mybatis整合

 

分享到:
评论

相关推荐

    springmybatis

    mybatis实战教程mybatis in action之一开发环境搭建 mybatis实战教程mybatis in action之二以接口的方式编程 mybatis实战教程mybatis in action之三实现数据的增删改查 mybatis实战教程mybatis in action之四实现...

    互联网轻量级SSM框架解密:Spring、Spring MVC、MyBatis源码深度剖析

    突破Java Web 研发瓶颈的束缚,选取Spring、SpringMVC 和MyBatis 框架中易于理解的版本,深入剖析了其中各个模块的实现,从代码中挖掘常用的设计模式,为读者理解Spring 系列框架的可扩展设计艺术提供了方法论和优秀...

    Spring3MVC+MyBatis+ExtJs3整合开发系列之四:角色管理模块

    在本篇博文中,我们将深入探讨“Spring3MVC+MyBatis+ExtJs3整合开发系列之四:角色管理模块”。这个主题涉及到三个关键的技术栈:Spring MVC作为后端MVC框架,MyBatis作为持久层解决方案,以及Ext Js 3作为前端UI库...

    jee、spring、spring mvc、mybatis 学习(五)

    在本篇【jee、spring、spring mvc、mybatis 学习(五)】中,我们将深入探讨四个关键的Java企业级开发技术:Java EE(Java Enterprise Edition)、Spring框架、Spring MVC以及MyBatis。这些技术是现代Java Web应用...

    java,Javaweb开发,spring+springmvc+mybatis整合视频及maven使用及实战视频

    本篇将详细介绍 Java Web 开发的基础知识,包括 Java Web 的概念、常用框架(Spring、Spring MVC 和 MyBatis)以及构建工具 Maven 的使用。 ### Java Web 概念 Java Web 主要指通过 Java 技术来实现的 Web 应用...

    Mybatis由浅入深 - 02基础CRUD

    这是Mybatis系列的第2篇,重实战,说人话,讲干活,全部原创,不抄袭,博文地址:https://blog.csdn.net/scm_2008/article/details/126574504 欢迎各位下载学习

    jee、spring、spring mvc、mybatis 学习(十)

    在本篇博客“JEE、Spring、Spring MVC、MyBatis 学习(十)”中,作者深入探讨了这四个关键的Java企业级开发技术,它们是构建现代Web应用程序的基础。下面将对这些技术进行详细阐述。 1. JEE(Java Enterprise ...

    【疯狂软件】Spring+mybaits企业实战

    在本篇关于《疯狂软件》系列图书的内容介绍中,我们关注的是以Spring框架和MyBatis持久层框架为核心的Java企业级应用实战。Spring框架是一个开源的Java平台,主要负责简化企业级应用开发,它能够提供企业服务的抽象...

    javaweb开发实战1200例第二卷源码

    此外,书中还可能涵盖了MVC(Model-View-Controller)设计模式,Spring框架的使用,以及如何集成Struts、Hibernate、MyBatis等流行框架。Spring框架提供了依赖注入、AOP(面向切面编程)等功能,大大简化了Java Web...

    JAVAWEB开发实战经典(李兴华)配套视频下载地址

    - **MVC模式:** MVC即Model-View-Controller模式,是JavaWeb开发中最常用的架构模式之一。它将应用程序分为三个部分:模型(Model)、视图(View)和控制器(Controller)。 - **分层架构:** 在实际开发中,通常会采用...

    基于Java的大众点评项目实战设计源码

    本篇文章将对基于Java的大众点评项目实战设计源码进行深度剖析,帮助读者理解并掌握相关技术要点。 首先,项目采用Java作为主要开发语言,体现了Java在大型复杂系统中的应用能力。Java的面向对象特性使得代码结构...

    J2EE高级框架实战

    本篇内容将深入探讨J2EE高级框架的实战应用。 1. **Spring框架**:作为J2EE最广泛使用的框架之一,Spring提供了一个全面的应用开发框架,包括依赖注入、AOP(面向切面编程)、MVC(模型-视图-控制器)和数据访问。...

    Android代码-java-bible

    Spring中怎么用 设计一个IOC 原理分析 设计模式系列 如何正确地写出单例模式 代理模式剖析 什么是策略模式 Java8系列 Java8简明教程 Java8 Foreach Hexo搭建博客 分分钟部署一个Hexo环境 各种配置详解 开始...

    24.1 SpringCloud电商实战2

    在本篇中,我们将深入探讨"24.1 SpringCloud电商实战2"的主题,这是对SpringCloud电商项目系列的延续,旨在提供一个基于Spring Cloud的实际应用案例。在上一部分"24.1 SpringCloud电商实战1"中,我们可能已经构建了...

    SpringBoot与Shiro整合-权限管理实战视频+源码

    ### SpringBoot与Shiro整合-权限管理实战视频+源码 ...通过本篇介绍,我们了解了如何在Spring Boot项目中集成Shiro,并实现了基于角色和权限的访问控制。这对于开发安全可靠的现代Web应用来说至关重要。

    一个很有用的sturts实战项目

    通过这个实战项目,开发者可以学习到如何将 Struts 与 JDBC、Hibernate 或 MyBatis 等持久层框架集成,处理表单数据,实现动态导航,以及使用 AJAX 进行异步通信等。同时,也可以提升对 MVC 设计模式的理解,增强...

    [轻量级Java_EE企业应用实战

    根据提供的标题、描述和标签,我们可以推断出这篇文章主要探讨的是“轻量级Java EE企业应用实战”的相关内容。虽然给出的部分内容仅为一个重复的链接,我们依然可以从标题和描述出发,构建一系列与轻量级Java EE企业...

    GameStore.zip

    本篇文章将深入探讨如何利用Spring、SpringMVC、MyBatis三大主流Java框架,结合MySQL数据库,构建一个名为“GameStore”的游戏商店系统。该系统涵盖了游戏的上架、下架、价格调整、图片管理以及客户端的预览、购买和...

    java技能百练--数据库篇

    "Java技能百练--数据库篇"可能涵盖了一系列关于如何使用Java与各种数据库进行交互的教程或实践项目。这个压缩包文件很可能是为了帮助开发者提升在Java环境中处理数据库的能力而设计的。 在Java中,我们通常使用JDBC...

    从0开始-大数据技术学习思路.docx

    推荐阅读《Spring 实战(第 4 版)》、《精通 SpringMVC(第四版)》、《MyBatis 从入门到精通》和《Spring Boot 编程思想(核心篇)》。 6. **分布式服务**:了解 Linux 基础,Maven 构建工具,以及 Apache Dubbo ...

Global site tag (gtag.js) - Google Analytics