摘要:本章主要介紹的是的基礎(chǔ)應(yīng)用和源碼涉及的相關(guān)等,主要包含的內(nèi)容有的簡(jiǎn)介反射動(dòng)態(tài)代理包含代理和代理使用和代碼生成器等。組件生命周期,如圖測(cè)試代碼生成器代碼生成器,又稱逆向工程。
本章主要介紹的是MyBatis的基礎(chǔ)應(yīng)用和源碼涉及的相關(guān)等,主要包含的內(nèi)容有MyBatis的簡(jiǎn)介、反射、動(dòng)態(tài)代理(包含JDK代理和cglib代理)、MyBatis使用和代碼生成器等。
1.1 MyBatis簡(jiǎn)介MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。MyBatis 可以使用簡(jiǎn)單的 XML 或注解來(lái)配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄。
關(guān)于MyBatis相關(guān)的信息,大家可以參考如下:
MyBatis官網(wǎng): http://www.mybatis.org/
MyBatis文檔: http://www.mybatis.org/mybati...
MyBatis源碼地址: https://github.com/mybatis/my...
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為java語(yǔ)言的反射機(jī)制。
JAVA反射(放射)機(jī)制:“程序運(yùn)行時(shí),允許改變程序結(jié)構(gòu)或變量類型,這種語(yǔ)言稱為動(dòng)態(tài)語(yǔ)言”。從這個(gè)觀點(diǎn)看,Perl,Python,Ruby是動(dòng)態(tài)語(yǔ)言,C++,Java,C#不是動(dòng)態(tài)語(yǔ)言。但是JAVA有著一個(gè)非常突出的動(dòng)態(tài)相關(guān)機(jī)制:Reflection,用在Java身上指的是我們可以于運(yùn)行時(shí)加載、探知、使用編譯期間完全未知的classes。換句話說(shuō),Java程序可以加載一個(gè)運(yùn)行時(shí)才得知名稱的class,獲悉其完整構(gòu)造(但不包括methods定義),并生成其對(duì)象實(shí)體、或?qū)ζ鋐ields設(shè)值、或喚起其methods。
從實(shí)用的角度看,筆者認(rèn)為有如下幾個(gè)場(chǎng)景?大家可以做一個(gè)思考。
(1) 逆向代碼,例如反編譯;
(2) 與注解結(jié)合的框架,現(xiàn)在有不少java框架都采用注解的方式,例如Spring既可以通過(guò)注解管理事務(wù)又可以通過(guò)XML方式管理事務(wù);
(3) 插件系統(tǒng), 程序設(shè)計(jì)了加載新JAR的功能,陌生JAR文件在程序運(yùn)行時(shí)加入,被編譯成class文件,通過(guò)反射機(jī)制加載進(jìn)內(nèi)存;
(4) 配置文件中的休眠class類, 一個(gè)程序有許許多多功能,不可能相對(duì)應(yīng)的class文件一次性全部加載進(jìn)內(nèi)存,只能是加載進(jìn)維持程序運(yùn)行的基本class,其余功能只有等用的時(shí)候,采用觸發(fā)機(jī)制,通過(guò)xml配置文件獲取類名等信息,然后通過(guò)反射機(jī)制加載相關(guān)class進(jìn)內(nèi)存。
1.2.3 反射實(shí)例代碼如下:
package cn.reflect; import java.lang.reflect.Method; public class ReflectService { /** * 測(cè)試方法 * @param name */ public void testReflect(String name) { System.out.println("hello:"+name); } /** * 測(cè)試入口 * @throws Exception */ public static void main(String[] args) throws Exception { /** * 通過(guò)反射創(chuàng)建ReflectService對(duì)象 */ Object service = Class.forName(ReflectService.class.getName()).newInstance(); /** * 獲取服務(wù)方法 */ Method method = service.getClass().getMethod("testReflect", String.class); method.invoke(service, "張三"); } }1.2.4反射的優(yōu)缺點(diǎn)
反射在給我們帶來(lái)極大的便利的同時(shí),也帶給我們潛在的危害。這也就是有利也有弊。
反射的優(yōu)點(diǎn):
反射提高了程序的靈活性和擴(kuò)展性,降低耦合性,提高自適應(yīng)能力。它允許程序創(chuàng)建和控制任何類的對(duì)象,無(wú)需提前硬編碼目標(biāo)類。
反射的缺點(diǎn):
(1)性能問(wèn)題:使用反射基本上是一種解釋操作,用于字段和方法接入時(shí)要遠(yuǎn)慢于直接代碼。因此反射機(jī)制主要應(yīng)用在對(duì)靈活性和擴(kuò)展性要求很高的系統(tǒng)框架上,普通程序不建議使用。
(2)使用反射會(huì)模糊程序內(nèi)內(nèi)部邏輯:程序員希望在源代碼中看到程序的邏輯,反射等繞過(guò)了源代碼的技術(shù),因而會(huì)帶來(lái)維護(hù)問(wèn)題。反射代碼比相應(yīng)的直接代碼更復(fù)雜。
1.3 動(dòng)態(tài)代理 1.3.1 動(dòng)態(tài)代理簡(jiǎn)介動(dòng)態(tài)代理有兩種方式,一種是JDK的代理,另外一種是cglib代理。
它們之間的區(qū)別是,JDK是代理接口,cglib代理類。
換言之,一個(gè)是接口方式,一個(gè)是類的方式,類的方式通常表現(xiàn)為繼承。
步驟如下:
(1)編寫(xiě)接口類
HelloService.java
package cn.reflect; public interface HelloService { public void sayHello(String name); }
(2)編寫(xiě)實(shí)現(xiàn)類
HelloServiceImpl.java
package cn.reflect; public class HelloServiceImpl implements HelloService { public void sayHello(String name) { // TODO Auto-generated method stub System.err.println("hello:"+name); } }
(3)編寫(xiě)代理類
HelloServiceProxy.java
package cn.reflect; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class HelloServiceProxy implements InvocationHandler { /** * 真實(shí)服務(wù)對(duì)象 */ private Object target; public Object bind(Object target){ this.target=target; /** * 取得代理對(duì)象 */ return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);//jdk代理對(duì)象需要提供接口 } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println("我是JDK動(dòng)態(tài)代理對(duì)象"); Object result = null; /** * 反射方法調(diào)用前 */ System.out.println("我準(zhǔn)備說(shuō)hello"); /** * 執(zhí)行方法,相當(dāng)于調(diào)用HelloServiceImpl中的sayHello方法 */ result = method.invoke(target, args); /** * 反射方法后調(diào)用 */ System.out.println("我說(shuō)過(guò)hello了"); return result; } }
(4)編寫(xiě)運(yùn)行測(cè)試類
HelloServiceMain.java
package cn.reflect; public class HelloServiceMain { public static void main(String[] args) { HelloServiceProxy helloHandle = new HelloServiceProxy(); HelloService proxy = (HelloService) helloHandle.bind(new HelloServiceImpl()); proxy.sayHello("張三"); } }1.3.3 cglib代理應(yīng)用實(shí)例
JDK提供的動(dòng)態(tài)代理存在缺陷,必須提供接口才能使用,沒(méi)有接口就不能使用,為了克服這個(gè)缺陷,我們可以采用cglib代理,它是一種流行的動(dòng)態(tài)代理。
步驟如下:
(1) 導(dǎo)入maven依賴
cglib cglib 3.2.4
(2) 編寫(xiě)運(yùn)行測(cè)試類
HelloServiceCgLib.java
package cn.reflect; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class HelloServiceCgLib implements MethodInterceptor{ private Object target; /** * 創(chuàng)建代理對(duì)象 */ public Object getInstance(Object target) { this.target=target; Enhancer enHancer = new Enhancer(); enHancer.setSuperclass(this.target.getClass()); enHancer.setCallback(this); return enHancer.create(); } public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable { // TODO Auto-generated method stub System.out.println("我是cglib代理對(duì)象"); Object returnObj = proxy.invoke(obj, arg); /** * 反射方法前調(diào)用 */ System.out.println("我準(zhǔn)備說(shuō)hello"); /** * 反射方法后調(diào)用 */ System.out.println("我說(shuō)過(guò)hello了"); return returnObj; } }1.4 MyBatis使用 1.4.1 導(dǎo)入依賴
由于采用的是maven,只需引入maven對(duì)應(yīng)的依賴即可,通常情況下,只要maven依賴導(dǎo)入準(zhǔn)確,一般情況下很少會(huì)出現(xiàn)因?yàn)橐蕾嚊_突的問(wèn)題導(dǎo)致項(xiàng)目運(yùn)行失敗。
pom.xml
1.4.2 準(zhǔn)備SQL腳本4.0.0 cn.youcong.mybatis mybatis 0.0.1-SNAPSHOT org.mybatis mybatis 3.4.6 mysql mysql-connector-java 5.1.38 junit junit 4.12 test
CREATE TABLE `user` ( `user_id` int(8) NOT NULL AUTO_INCREMENT COMMENT "用戶主鍵", `login_code` varchar(20) NOT NULL COMMENT "用戶編碼(登錄賬戶) 手機(jī)號(hào) 郵箱號(hào)", `user_name` varchar(20) NOT NULL COMMENT "用戶名", `password` varchar(40) NOT NULL COMMENT "密碼", `sex` int(2) NOT NULL COMMENT "性別", `identity_card` varchar(20) DEFAULT NULL COMMENT "身份證", `create_time` datetime NOT NULL COMMENT "創(chuàng)建時(shí)間", `create_by` varchar(10) NOT NULL COMMENT "創(chuàng)建人", `update_time` datetime NOT NULL COMMENT "更新時(shí)間", `update_by` varchar(10) NOT NULL COMMENT "更新人", `status` int(2) NOT NULL DEFAULT "0" COMMENT "狀態(tài):0注冊(cè)新用戶 1郵件認(rèn)證用戶 2管理員 3黑名單", PRIMARY KEY (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;1.4.3 編寫(xiě)實(shí)體
package com.blog.entity; import java.io.Serializable; import java.util.Date; import java.io.Serializable; public class User{ private static final long serialVersionUID = 1L; /** * 用戶主鍵 */ private Integer userId; /** * 用戶編碼(登錄賬戶) 手機(jī)號(hào) 郵箱號(hào) */ private String loginCode; /** * 用戶名 */ private String userName; /** * 密碼 */ private String password; /** * 性別 */ private Integer sex; /** * 身份證 */ private String identityCard; /** * 創(chuàng)建時(shí)間 */ private Date createTime; /** * 創(chuàng)建人 */ private String createBy; /** * 更新時(shí)間 */ private Date updateTime; /** * 更新人 */ private String updateBy; /** * 狀態(tài):0注冊(cè)新用戶 1郵件認(rèn)證用戶 2管理員 3黑名單 */ private Integer status; public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } public static long getSerialversionuid() { return serialVersionUID; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getLoginCode() { return loginCode; } public void setLoginCode(String loginCode) { this.loginCode = loginCode; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } public String getIdentityCard() { return identityCard; } public void setIdentityCard(String identityCard) { this.identityCard = identityCard; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getCreateBy() { return createBy; } public void setCreateBy(String createBy) { this.createBy = createBy; } public String getUpdateBy() { return updateBy; } public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } }1.4.4 編寫(xiě)數(shù)據(jù)訪問(wèn)層及其對(duì)應(yīng)的XML文件
package com.blog.dao; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import com.blog.entity.User; public interface UserDao { @Select("select * from `user` where user_id=#{userId}") @Results(@Result(property="userName",column="user_name")) User selectOne(int userId); }
@Select是MyBatis的注解寫(xiě)法,當(dāng)字段名和屬性名一致時(shí),可以直接@Select不需要@Results,@Results的作用就是因?yàn)閷?shí)體屬性與字段不一致,為了獲取查詢結(jié)果,必須要這樣。
當(dāng)然了你也可以不寫(xiě)注解,直接在對(duì)應(yīng)的UserDao.xml寫(xiě),如果是UserDao.xml里面寫(xiě)的話,就會(huì)變成這樣
package com.blog.dao; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import com.blog.entity.User; public interface UserDao { User selectOne(int userId); }
需要在UserDao.xml中編寫(xiě)
user_id, login_code, user_name, password, sex, identity_card, create_time, create_by, update_time, update_by, status
除了
user_id, login_code, user_name, password, sex, identity_card, create_time, create_by, update_time, update_by, status
MyBatis常用的兩種寫(xiě)法,XML方式和注解方式,但是無(wú)論你采用哪種,對(duì)應(yīng)的XML文件必須要存在。
其實(shí)
前提必須要在mybatis-config.xml配置
但是有人覺(jué)得,如果我的類有很多,豈不是要配置很多,太麻煩了,別怕,MyBatis已經(jīng)為你想到了
這樣配置就解決了重復(fù)配置的麻煩
其實(shí)除了這樣,如果你想標(biāo)新立異點(diǎn),還可以再實(shí)體最上面加上@Alias注解
這就是MyBatis的別名三種方式/策略。
1.4.5 編寫(xiě)mybatis-config.xml配置文件mybatis-config.xml這個(gè)配置沒(méi)多大用,坦白說(shuō)。
因?yàn)楹笃谂cSpring整合由Spring來(lái)管理數(shù)據(jù)庫(kù)連接池對(duì)象。
不過(guò)還是要稍微講講,以讓讀者達(dá)到開(kāi)卷有益的目的或者是讓沒(méi)有學(xué)過(guò)的或者已經(jīng)學(xué)過(guò)但是不知道的漲漲見(jiàn)識(shí)。
package com.blog.config; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class SqlSessionFactoryUtils { private static SqlSessionFactory sqlSessionFactory = null; public static SqlSessionFactory getSqlSessionFactory() { InputStream is = null; if(sqlSessionFactory==null) { String resource = "mybatis/mybatis-config.xml"; try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(resource)); return sqlSessionFactory; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return sqlSessionFactory; } }
說(shuō)到上述代碼,順便談?wù)凪yBatis的核心組件。它的核心組件主要有這么幾個(gè),如下所示:
SqlSessionFactoryBuilder:它會(huì)根據(jù)配置信息或者代碼來(lái)生成SqlSessionFactory;
SqlSessionFactory:依賴工廠生成SqlSession;
SqlSession:是一個(gè)即可發(fā)送SQL執(zhí)行返回結(jié)果,也可以獲取Mapper接口;
Sql Mapper:它是MyBatis的新設(shè)計(jì)組件,它是由一個(gè)Java接口和XML文件(或注解)構(gòu)建,需要給出對(duì)應(yīng)的SQL和映射規(guī)則。它負(fù)責(zé)發(fā)送SQL去執(zhí)行并返回結(jié)果。
用一張圖來(lái)表示它們之間的關(guān)系,如圖:
它們的生命周期在此稍微說(shuō)一下:
(1)SqlSessionFacotoryBuilder
SqlSessionFacotoryBuilder是利用XML和Java代碼獲得資源來(lái)構(gòu)建SqlSessionFactory的,通過(guò)它可以構(gòu)建多個(gè)SqlSessionFactory,它的作用就是一個(gè)構(gòu)建器,一旦我們構(gòu)建了SqlSessionFactory,它的作用就完結(jié),它就失去存在的意義。這時(shí)我們應(yīng)該毫不猶豫的廢棄它,將它回收。所以它的生命周期只存在方法局部,它的作用就是生成SqlSessionFactory。
(2)SqlSessionFactory的作用是創(chuàng)建SqlSession,而SqlSession就是一個(gè)會(huì)話,相當(dāng)于JDBC中的Connection對(duì)象。每次應(yīng)用程序需要訪問(wèn)數(shù)據(jù)庫(kù),我們就要通過(guò)SqlSessionFactory創(chuàng)建SqlSession,所以SqlSessionFactory應(yīng)該在MyBatis應(yīng)用的整個(gè)生命周期中。而如果我們多次創(chuàng)建同一個(gè)數(shù)據(jù)庫(kù)的SqlSessionFactory,則每次創(chuàng)建SqlSessionFactory會(huì)打開(kāi)更多的數(shù)據(jù)庫(kù)連接資源,那么連接資源就很快會(huì)被耗盡。因此SqlSessionFactory的責(zé)任是唯一的,它的責(zé)任就是創(chuàng)建SqlSession,所以我們果斷采用單例模式。如果采用多例,那么它對(duì)數(shù)據(jù)庫(kù)連接的消耗是很大的,不利于我們統(tǒng)一管理。所以正確的做法是使得每個(gè)數(shù)據(jù)庫(kù)只對(duì)應(yīng)一個(gè)SqlSessionFactory,管理好數(shù)據(jù)庫(kù)資源分配,避免過(guò)多的Connection被消耗。
(3)SqlSession
SqlSession是一個(gè)會(huì)話,相當(dāng)于JDBC的一個(gè)Connection對(duì)象,它的生命周期應(yīng)該是在請(qǐng)求數(shù)據(jù)庫(kù)處理事務(wù)的過(guò)程中。它是一個(gè)線程不安全的對(duì)象,在涉及多線程的時(shí)候我們需要特別當(dāng)心,操作數(shù)據(jù)庫(kù)需要注意其隔離級(jí)別,數(shù)據(jù)庫(kù)鎖等高級(jí)特性。此外,每次創(chuàng)建的SqlSession都必須及時(shí)關(guān)閉它,它長(zhǎng)期存在就會(huì)使數(shù)據(jù)庫(kù)連接池的活動(dòng)資源減少,對(duì)系統(tǒng)性能的影響很大。
(4)Mapper
Mapper是一個(gè)接口,而沒(méi)有任何實(shí)現(xiàn)類,它的作用是發(fā)送SQL,然后返回我們需要的結(jié)果,或者執(zhí)行SQL從而修改數(shù)據(jù)庫(kù)的數(shù)據(jù),因此它應(yīng)該在一個(gè)SqlSession事務(wù)方法之內(nèi),是一個(gè)方法級(jí)別的東西。它就如同JDBC中的一條SQL語(yǔ)句的執(zhí)行,它的最大范圍和SqlSession是相同的。盡管我們想一直保存著Mapper,但是你會(huì)發(fā)現(xiàn)它很難控制,所以盡量在一個(gè)SqlSession事務(wù)的方法中使用它們,然后廢棄掉。
MyBatis組件生命周期,如圖:
1.4.7 測(cè)試package mybatis; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import com.blog.config.SqlSessionFactoryUtils; import com.blog.dao.UserDao; import com.blog.entity.User; public class MyBatisTest { @Test public void testName() throws Exception { SqlSession sqlSession = null; sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); User user = userDao.selectOne(1); System.out.println(user.getUserName()); } }1.5 MyBatis代碼生成器
MyBatis代碼生成器,又稱逆向工程。
關(guān)于逆向工程的優(yōu)點(diǎn)和缺點(diǎn),我覺(jué)得我還是要說(shuō)說(shuō)。
逆向工程的優(yōu)點(diǎn)是:自動(dòng)化生成實(shí)體類和對(duì)應(yīng)的增刪改查,效率相對(duì)于之前個(gè)人開(kāi)發(fā)時(shí)一個(gè)個(gè)寫(xiě)增刪改查要高的多
逆向工程的缺點(diǎn)是:xml中的sql語(yǔ)句加入了mybatis自身的動(dòng)態(tài)sql和一大堆判斷等,對(duì)于對(duì)動(dòng)態(tài)sql不是十分熟練的人而言,以后再功能擴(kuò)展上會(huì)很困難。
================
MyBatis代碼生成器我分為兩個(gè),一個(gè)是動(dòng)態(tài)web工程,另一個(gè)是現(xiàn)在比較流行的maven工程,本質(zhì)上都是一樣,只是項(xiàng)目管理jar包的方式不一樣。
(1)導(dǎo)包
(2)新建generator.xml文件,進(jìn)行配置
(3)測(cè)試
import java.io.File; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.internal.DefaultShellCallback; public class GeneratorSqlmap { public void generator() throws Exception{ Listwarnings = new ArrayList (); boolean overwrite = true; //指定 逆向工程配置文件 File configFile = new File("src/generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap(); generatorSqlmap.generator(); } catch (Exception e) { e.printStackTrace(); } } }
測(cè)試結(jié)果在控制臺(tái)打印如下,表示成功
1.5.2 maven工程(1)導(dǎo)入maven依賴
4.0.0 cn.mybatis.generator mybatis-generator 0.0.1-SNAPSHOT UTF-8 mysql mysql-connector-java 5.1.35 org.mybatis.generator mybatis-generator-core 1.3.2 org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 3.3 org.mybatis.generator mybatis-generator-maven-plugin 1.3.2 mysql mysql-connector-java 5.1.35 src/main/resources/generatorConfig.xml true
(2)在src/main/resource目錄下新建配置文件generatorConfig.xml
(3)右擊進(jìn)入run as 點(diǎn)擊maven build 如下圖輸入:mybatis-generator:generate
運(yùn)行結(jié)果如下,表示成功
注意:運(yùn)行成功后,直接是看不到生成的代碼,還需要刷新一下(refresh)。
1.6 小結(jié)通過(guò)上面的內(nèi)容,我相信讀者對(duì)于MyBatis已經(jīng)有了大致的了解,通過(guò)相關(guān)的代碼示例,我相信讀者應(yīng)該知道怎么使用MyBatis了。當(dāng)然了,這僅僅只是MyBatis的冰山一角,MyBatis的特性還有很多。不過(guò)我之所以講MyBatis也是為了后續(xù)讀者更好理解MyBatis-plus。
本文主要參考我個(gè)人的博客園中的MyBatis系列相關(guān)的,可以說(shuō)這篇文章是之前MyBatis相關(guān)教程不太完善的補(bǔ)充。希望能夠幫助到大家。
最后,如需轉(zhuǎn)載本文,請(qǐng)附源地址,謝謝合作。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/72724.html
摘要:是最流行的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)之一,在應(yīng)用方面,是最好的,關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)應(yīng)用軟件。是一種關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng),關(guān)系數(shù)據(jù)庫(kù)將數(shù)據(jù)保存在不同的表中,而不是將所有數(shù)據(jù)放在一個(gè)大倉(cāng)庫(kù)內(nèi),這樣就增加了速度并提高了靈活性。 本章主要是對(duì)MyBatis-Plus的初步介紹,包括一些背景知識(shí)、環(huán)境搭建、初步使用等知識(shí)和例子。對(duì)于背景知識(shí),主要包含對(duì)MyBatis-Plus的特性介紹、為什么使用MyB...
摘要:跟兩年前寫(xiě)和配置相關(guān)的文件相比,這真是十分的簡(jiǎn)單了??梢栽囍鴮?xiě)一個(gè)小小的,有很多視頻教程跟著一步步做就成,我是跟著慕課網(wǎng)上的視頻學(xué)習(xí)的。對(duì)于寫(xiě)快一年的我來(lái)說(shuō)初學(xué)這個(gè)還是很欣喜的。 環(huán)境配置 Mac 上搭建 java 開(kāi)發(fā)環(huán)境http://starzhou.com/blogs/jav... 初始化項(xiàng)目 參考鏈接http://start.spring.io/ 從此鏈接中輸入項(xiàng)目名,并選擇相...
摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開(kāi)發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過(guò)的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛(ài)情萌芽的模樣…… Java 進(jìn)階面試問(wèn)題列表 -...
摘要:各方面有各種常見(jiàn)的良好示例,包括日志記錄,聲明式事務(wù),安全性,緩存等。聲明式事務(wù)管理這意味著你從業(yè)務(wù)代碼中分離事務(wù)管理。但作為一種橫切關(guān)注點(diǎn),聲明式事務(wù)管理可以使用方法進(jìn)行模塊化。支持使用框架的聲明式事務(wù)管理。 本章主要內(nèi)容包括Spring簡(jiǎn)介、Spring的兩大特性(IOC和AOP)、事務(wù)MyBatis集成Spring等。也許有讀者會(huì)疑惑,明明是MyBatis-Plus實(shí)戰(zhàn),怎么還講...
閱讀 2943·2023-04-25 20:02
閱讀 1582·2021-11-11 16:55
閱讀 727·2021-09-26 09:46
閱讀 6600·2021-09-22 15:55
閱讀 1904·2021-08-09 13:41
閱讀 1654·2019-08-30 15:52
閱讀 2463·2019-08-30 14:13
閱讀 3520·2019-08-26 13:48