1. 程式人生 > >MyBatis由淺入深學習總結之二:MyBatis解決Java實體類和資料庫表字段不一致方法總結

MyBatis由淺入深學習總結之二:MyBatis解決Java實體類和資料庫表字段不一致方法總結

在此,首先說明一點任何永續性框架都需要解決一個問題,那就是Java實體類的欄位一般來說基本上會與資料庫表中欄位不一致,那麼它們是如何解決的呢?咱們以Hibernate和SpringJDBC為例說明一下;

1、Hibernate中一般通過XML對映和註解的方式解決不一致問題,看下面兩個簡單例子,

註解方式:

@Entity
@Table(name = "ACCOUNT")
public class Account implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private int id;

	@Column(name="fld_number")
	private String number;
	
	@OneToMany(mappedBy="account")
	private Set<Client> clients;
	
	private double balance;

}
XML對映檔案配置方式:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="org.hibernate.test.domain.Account" table="ACCOUNT" lazy="false">
        <id name="id" column="ACCOUNT_ID">
            <generator class="native"/>
        </id>

        <many-to-one name="person" class="org.hibernate.test.domain.Person" cascade="save-update,lock"
                     column="person_id"
                     unique="true"
                     not-null="true"/>
    </class>

</hibernate-mapping>
2、Spring JDBC一般通過使用RowCallbackHandler和RowMapper,編寫回調函式的方式處理不一致,各種方法如下所示:


好的,瞭解完上述兩種方式,咱們再來看看對於同樣的問題,MyBatis是如何處理的?

對於這種問題,MyBatis主要提供了兩種方式用來解決該問題;

一、通過對查詢SQL採用欄位別名的方式

1、新建表和插入資料

DROP TABLE IF EXISTS `sl_company`;
CREATE TABLE `sl_company` (
  `company_id` int(11) NOT NULL AUTO_INCREMENT,
  `company_name` varchar(50) DEFAULT NULL,
  `full_name` varchar(100) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL,
  `post_code` varchar(45) DEFAULT NULL,
   PRIMARY KEY (`company_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sl_company
-- ----------------------------
INSERT INTO `sl_company` VALUES ('1', '銳客科技', '上海銳客科技股份有限公司', '上海市浦東新區峨山路91弄97號陸家嘴軟體園5號樓3層', '200127');
2、建立對應的實體類
package com.mybatis.entity;

import java.io.Serializable;

public class SlCompany implements Serializable {

	private static final long serialVersionUID = 1L;

	private int companyId;

	private String companyName;

	private String fullName;

	private String address;

	private String postCode;

	public SlCompany() {
		super();
	}

	public int getCompanyId() {
		return companyId;
	}

	public void setCompanyId(int companyId) {
		this.companyId = companyId;
	}

	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	public String getFullName() {
		return fullName;
	}

	public void setFullName(String fullName) {
		this.fullName = fullName;
	}

	public String getAddress() {
		return address;
	}

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

	public String getPostCode() {
		return postCode;
	}

	public void setPostCode(String postCode) {
		this.postCode = postCode;
	}
	
}
3、上述建立完成後可以很明顯發現欄位名稱與屬性名稱不一致,繼續看如何解決該問題,找到slCompanyMapper.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.mybatis.mappings.slCompanyMapper">
	<!-- 通過使用欄位別名的方式,AS關鍵字前面的是資料庫表的欄位名,後面對應的Java實體類對應的屬性名稱 -->
	<select id="getSlCompany" parameterType="int"
		resultType="com.mybatis.entity.SlCompany">
		SELECT company_id AS companyId,company_name AS
		companyName,full_name AS fullName, post_code AS postCode, address FROM
		sl_company WHERE company_id=#{id}
	</select>
</mapper>
4、執行測試類,發現通過上述方式,仍然執行出既定結果,需要說明的是如果欄位過多、過長,我們可以繼續採用下面方式,將欄位列表單獨映射出來,用的時候直接匯入即可,如下所示:
<?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.mybatis.mappings.slCompanyMapper">
	<!-- 通過使用欄位別名的方式,AS關鍵字前面的是資料庫表的欄位名,後面對應的Java實體類對應的屬性名稱 -->
	<!-- SlCompany欄位對映列表 -->
	<sql id="getSlCompanyColumns">
		company_id AS companyId,
		company_name AS companyName,
		full_name AS fullName, 
		post_code AS postCode, 
		address 
	</sql>
	<!-- 通過使用include元素的refid屬性引入上面自定義的對映列表 -->
	<select id="getSlCompany" parameterType="int" resultType="com.mybatis.entity.SlCompany">
		SELECT <include refid="getSlCompanyColumns"/> FROM	sl_company WHERE company_id=#{id}
	</select>
</mapper>
二、通過在xml中自定義結果對映的方式

1、表結構與java實體類同上,不在贅述。

2、下面來看看對映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.mybatis.mappings.slCompanyMapper">
	<!-- 通過使用結果對映的方式 -->
	<select id="getSlCompany2" parameterType="int" resultMap="slCompanyResultMap">
		SELECT * FROM sl_company WHERE company_id=#{id}
	</select>
	
	<!-- 通過使用resultMap元素自定義結果對映,該元素內部的id和result提供了javaType、jdbcType、typeHandler屬性滿足型別要求 -->
	<resultMap type="com.mybatis.entity.SlCompany" id="slCompanyResultMap">
		<!-- 通過id元素對映主鍵型別 -->
		<id column="company_id" property="companyId" />
		<!-- 通過result元素對映非主鍵型別 -->
		<result column="company_name" property="companyName"/>
		<result column="full_name" property="fullName"/>
		<!-- 當欄位名和屬性名一致是,可寫可不寫 -->
		<result column="address" property="address"/>
		<result column="post_code" property="postCode"/>
	</resultMap>
	
</mapper>
3、執行簡單輸出類
package com.mybatis.test;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.mybatis.entity.SlCompany;

public class MyBatisTest {
	
	public static void main(String[] args) throws IOException {
		
		// mybatis提供了Resources類用來提供簡易方式來獲取各種來源的資原始檔資訊
		// 獲取mybatis.xml的位元組流
		InputStream is = Resources.getResourceAsStream("mybatis.xml");
		// 獲取mybatis.xml的字元流
		//Reader reader = Resources.getResourceAsReader("mybatis.xml");
		
		// 構建SqlSessionFactory物件,傳入字元流或位元組流均可
		SqlSessionFactory SqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
		// 獲取SqlSession物件
		SqlSession sqlSession = SqlSessionFactory.openSession();
		
		// 執行查詢操作
		// selectOne()方法的第一個引數是由slCompanyMapper.xml裡配置的mapper的namespace屬性 + 該mapper下select元素的id屬性值組成的
		SlCompany slCompany = sqlSession.selectOne("com.mybatis.mappings.slCompanyMapper.getSlCompany2", 1);
		
		// 用完SqlSession之後,不要忘記關閉
		sqlSession.close();
		
		System.out.println(slCompany.getAddress());
	}
}
輸出既定資訊;

總結:無論上述哪一種方式都提供了一種解決不一致的途徑,需要注意它倆的不同點;

第一種方式直接在查詢SQL語句下手,通過採用別名的方式,也就是說這種方式在得到查詢結果集之前就搞定了不一致問題,獲取到了跟屬性名稱一致的結果集;

第二種方式是在獲取結果集之後,對結果集下手;