[toc]html
simple-orm-mybatis在github開源,直接跳轉查看,歡迎你們fork和star。有什麼建議也能夠提出,我會盡快修復或實現。java
最先接觸Java的web開發框架就是SSH,其中的H就是Hibernate。Hibernate做爲最出名的Java的ORM框架,如今的版本已經到了5.3.10.Final,6.0.0.Alpha2。圍繞數據持久化或者DAL層也發展了多種工具,Hibernate Validator目前也是在不少的企業框架中被用做數據有效性檢查。 接下來還有用過JPA來實現ORM。JPA全稱Java Persistence API,是JSR-220(EJB3.0)規範的一部分,在JSR-220中規定實體對象(EntityBean)由JPA進行支持。在個人使用中,實際上底層實現仍然使用了Hibernate,只是標註或者操做類都是使用了JPA的接口標準而沒有直接使用Hibernate。 Hibernate具備強大的ORM封裝能力,極大的簡化了CUD的操做,並且無需作太多的配置,使用標準註解就能解決不少問題。簡單的查詢操做也不在話下,多級關聯、延遲查詢等豐富特性基本上也能夠說是極大覆蓋了開發過程的各類需求。可是實際上在這麼多團隊中,不少人的反饋是這樣的:「Hibernate的ORM確實很方便,可是在一些特殊條件下很難用,好比複雜查詢就很難控制語句生成的效率」。Hibernate有三種查詢方式:HQL、Criteria、Native Sql。確實在複雜查詢下,若是使用Criteria,確實可以拼出想要的語句,可是可能對於其中的方法要很是熟悉,學習曲線很高,沒辦法作到團隊中每一個成員都能數量輕易的掌握,並且後期的審覈很困難沒法直接看清邏輯。HQL和NativeSql對個人感受,彷佛回到了JSP時代,HTML和Java代碼混寫,很難忍受。這時候你們找到了另外的框架Mybatis。mysql
截止(2019/5/27)Mybatis的Star是10806,UsedBy140381;Hibernate的Star是3817,UsedBy157879。看使用量Hibernate和Mybatis其實已經差很少了,實際企業開發中,Mybatis可能還會更多一些。git
Mybatis放棄了Hibernate的強封裝,主要包含了映射的部分,並且放棄了自動解析生成Sql,而直接使用用戶XML配置Sql的方式,只是在Sql的拼接上提供了一些標籤來避免重複代碼。這樣的討巧之處在於:github
缺點也有幾處:web
實際上,針對上面缺點,Mybatis也提供瞭解決方案。 先說sql id的,在新的Mybatis中,實際上已經採用了面向接口的編碼方式,以下面的例子:算法
接口類spring
public interface UserMapper { public User findUserById(Integer id); }
mapper的xml文件sql
<?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.software5000.mapper.dao.UserMapper"> <select id="findUserById" resultType="com.software5000.entity.User" parameterType="int" > select * from user where id =#{id} </select> </mapper>
這樣就能夠直接調用sql語句:數據庫
UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.findUserById(1);
再說映射覆雜的,Mybatis提供了MyBatis Generator做爲解決方案,一個命令生成下列內容:
自動生成也可以合理的生成類之間的繼承關係。注意生成器也可以定義生產不一樣的POJO層次 - 例如若是你想要能夠爲每一個表格生成一個單獨的領域對象。
生成的SQL語句取決於表格的結構(例如,表格若是沒有主鍵,就不會生成按主鍵更新的方法)
Java客戶端生成類可以合理使用上面的對象。生成的Java客戶端類也是有選擇性的。
可是,我對於MyBatis Generator的態度是堅決的反對。緣由是我認爲自動生成違反了簡單的原則,「如無必要,勿增實體」。自動生成的可複用性和可讀性必定是比較差的。我以爲最好的代碼就是不存在的代碼。所以我但願可以有一個簡單框架在Mybatis之上,接入簡單無侵入,可以提供基本的增刪改查方法。這就是下面的 simple-orm-mybatis 。
simple-orm-mybatis設計的初衷就是但願提供一個簡單無侵入,並且無需編寫或者生成任何代碼就可使用直接操做對象的方式來進行增刪改查的操做。要實現這樣的要求,主要是兩個主要技術點:
第一點核心就是反射,設計要點以下:
第二點核心在於SQL解析,設計要點以下:
<dependency> <groupId>com.software5000</groupId> <artifactId>simple-orm-mybatis</artifactId> <version>1.0.2</version> </dependency>
接着須要將 BaseDaoMapper.xml
文件放在你的 mapper 的掃描文件夾內。
最後須要在你的代碼中添加一個 BaseDao 實現類,用於提供數據庫操做服務(注意:須要在spring的掃描包內,由於須要注入某些屬性),整個複製便可,類名能夠改成你本身須要的名字
import com.software5000.base.BaseDao; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * 整個類以 <code>org.mybatis:mybatis-spring:2.0.0</code> 的 <code>org.mybatis.spring.supportSqlSessionDaoSupport</code> * 爲參考編寫而成 */ @Component public class MyBaseDao extends BaseDao { private SqlSessionTemplate sqlSessionTemplate; public MyBaseDao() { // 在默認構造函數中設置 數據庫是否蛇形, 數據庫格式大小寫, 通用忽略的字段名稱 this.initConfig(true,false,"serialVersionUID"); } @Resource public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) { this.sqlSessionTemplate = this.createSqlSessionTemplate(sqlSessionFactory); } } protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } @Override public SqlSession getSqlSession() { return this.sqlSessionTemplate; } }
這裏給了一個單元測試的例子,實際通常是在service層直接使用,無需添加任何代碼。 示例中的 DailyRecord
是一個普通實體類,沒有任何繼承。
// 獲取啓動類,加載配置,肯定裝載 Spring 程序的裝載方法,它回去尋找 主配置啓動類(被 @SpringBootApplication 註解的) @SpringBootTest // 讓 JUnit 運行 Spring 的測試環境, 得到 Spring 環境的上下文的支持 @RunWith(SpringRunner.class) public class BaseDaoTest { @Autowired private MyBaseDao myBaseDao; @Test public void testBaseDao(){ DailyRecord dailyRecord = new DailyRecord(); List<DailyRecord> dailyRecords = myBaseDao.selectEntity(dailyRecord); System.out.println(dailyRecords.size()); } }
雖然說總體的設計基於無侵入,基本沒有任何前提,可是仍是有一些推薦的實踐但願你們可以去嘗試:
一、 數據結構設計建議包含int類型的自增主鍵設計,名稱叫id。 緣由:不少時候咱們的業務主鍵是有一套特定規則,可是頗有可能面對修改,因此底層關聯主鍵統一使用id關聯在後期面對修改時影響較小。 弊端: 1. 如mysql中int最長2147483647,考慮到自增id可能會有跳過不連續的狀況,須要考慮實際可用的存儲量。不過大部分的業務表是到不了這個數量級的。 2. mysql的InnoDB有自增主鍵鎖表的問題,超大併發插入可能會影響效率。不過在5.1.22有提供了改進的策略。
二、 數據結構與實體結構儘可能符合統一轉換規則。 緣由:這樣研發過程當中,實體與數據庫的映射會比較簡單,無需大量的自定義。建議的規則有三類: - 兩邊都使用駝峯。 - 實體使用駝峯,數據庫使用全小寫蛇形 - 實體使用駝峯,數據庫使用全大寫蛇形
三、 代碼中實體的字段類型使用封裝類型而不是基本類型 緣由:基本類型是有默認值存在,而數據庫中咱們一旦設置字段可空,就會有NULL值存在。因此建議所有使用封裝類型。下面附上各類基本類型的默認值
基本類型 | 默認值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
char | ‘\u0000’ |
boolean | false |
四、 分頁算法 緣由:分頁推薦使用PageHelper,是利用Mybatis的底層插件機制修改Sql語句,也是無侵入。
更多說明,能夠參考github上的wiki頁面