《Java EE SSM框架》學習筆記(4)

項目路徑:https://share.weiyun.com/5oetQPG

 

MyBatis配置項的順序不能顛倒,如果顛倒了它們的順序,則啓動階段就會發生異常,導致程序無法運行。

使用property子元素:

這樣定義一次就可以到處引用了,如${database.username},但要定義的參數太多,則使用properties文件。

使用properties文件:

定義jdbc.properties文件

使用properties的屬性resource來引入properties文件:

解密用戶名和密碼後創建SqlSessionFactory

滿足運維人員對用戶名和密碼,保密的需求。

配置的優先級:程序傳遞方式 > properties文件的方式 > 使用property子元素的方式。

 

settings設置:

是MyBatis中最複雜的配置,能深刻影響MyBatis底層的運行,經常修改的一些規則:

自動映射、駝峯命名映射、級聯規則、是否啓動緩存、執行器類型。

配置是否啓動緩存:

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

 

typeAliases別名:

系統定義別名:

在MyBatis中別名由類TypeAliasRegistry去定義。

一般對基本類型int定義的別名爲,_int;類或包裝器類定義的別名爲,String爲string、List爲list、Long爲long。

通過Configuration獲取TypeAliasRegistry類對象

其中的,registerAlias方法去註冊別名;getTypeAliasRegistry方法獲取別名。

自定義別名:

可以支持掃描別名,自動將類名的第一個字母變爲小寫,作爲別名。

若出現衝突,則使用註解進行區分:

 

typeHandler類型轉換器:

在JDBC中,需要在PreparedStatement對象中設置那些,已經預編譯過的SQL語句的參數。

執行SQL後,通過ResultSet對象,獲取得到數據庫的數據。

在typeHandler中,分爲jdbcType和javaType,typeHandler的作用使其兩個類型相互轉換。

系統定義的typeHandler:

一般無須顯式聲明jdbcType和javaType,MyBatis會自己探測。

但一般枚舉類需要自己去編寫規則。

在MyBatis中typeHandler都要實現接口:org.apahe.ibatis.type.TypeHandler

系統註冊typeHandler:

一般自定義的typeHanlder不用代碼註冊,而是通過配置或掃描。

自定義typeHandler:

在xml中配置typeHandler:

啓用typeHandler的方式:

要麼指定了與typeHandler一致的jdbcType和javaType,要麼直接指定typeHandler具體實現類。

若一些數據從數據返回爲空,則採用指定與typeHandler一致的jdbcType和javaType的方法,避免系統不知採用哪個typeHandler處理,從而產生異常。

若typeHandler採用包掃描,則無法指定具體的jdbcType和javaType,可使用註解的方式配置:

 

枚舉typeHandler:

絕大多數情況下,typeHandler因爲枚舉而使用。

MyBatis已經定義了兩個類來支持,枚舉類型,但一般作用不大:

EnumOrdinalTypeHandler是根據,枚舉數組小標索引的方式,進行匹配的。

它要求數據庫返回一個整數(可以是以varchar作爲類型的整數)作爲其下標,根據下標找到對應的枚舉類型。

EnumTypeHandler會把使用的名稱轉化爲對應的枚舉。

如,數據庫返回的字符串“MALE”,進行Enum.valueOf(SexEnum.class,"MALE");轉換。

但是使用是上述兩種方式,會帶來很大的侷限性,一般自定義枚舉typeHandler。

 

文件操作:

若數據庫數據類型爲blog,java數據類型爲byte[],則使用BlogTypeHandler。

在現實中,一次性地將大量數據加載到JVM中,會給服務器帶來很大壓力。

因此,一般使用文件流的形式,所以,

數據庫數據類型爲blog,java數據類型爲InputStream,則使用BlogInputStreamTypeHandler

因爲性能不佳,大型互聯網的網站會採用文件服務器的形式。

 

ObjectFactory(對象工廠):

創建結果集時,會使用一個對象工廠來完成創建這個結果集實例。

一般情況,MyBatis會使用其定義的對象工廠——DefaultObjectFactory。

若要自定義對象工廠,則繼承DefaultObjectFactory:

public class MyObjectFactory extends DefaultObjectFactory {

    Logger log = Logger.getLogger(MyObjectFactory.class);

    private Object temp = null;

    @Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
        log.info("初始化參數:【" + properties.toString() + "】");
    }

    //方法二
    @Override
    public <T> T create(Class<T> type) {
        T result = super.create(type);
        log.info("創建對象:" + result.toString());
        log.info("是否和上次創建的是同一個對象:【" + (temp == result) + "】");
        return result;
    }

    //方法一
    @Override
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        T result = super.create(type, constructorArgTypes, constructorArgs);
        log.info("創建對象:" + result.toString());
        temp = result;
        return result;
    }

    @Override
    public <T> boolean isCollection(Class<T> type) {
        return super.isCollection(type);
    }
}

最後在配置文件對對象工廠進行配置:

運行結果是,先調用方法一,後調用方法二。

 

插件:

插件是MyBatis中最強大和靈活的組件,同時也是最複雜、最難以使用的組件,而且它十分危險。

應用它之前,一定要掌握底層的構成和運行原理。

 

environment(運行環境):

主要的作用是,配置數據庫信息,可配置多個數據庫。

下面又分爲兩個可配置的元素:事務管理器、數據源。

實際工作中,會採用Spring對數據源和數據庫的事務進行管理。

transactionManager(事務管理器):

transactionManager提供了兩個實現類,需要實現接口Transaction(提交、回滾、關閉等數據庫事務方法)

因此也對應兩個相應的工廠類,需實現TransactionFactory接口。

於是可把事務管理器配置成如下方式:

JDBC:以JDBC的方式對數據庫的提交和回滾進行操作。

MANAGED:把事務交給容器處理,可對closeConnection屬性設置爲false,來阻止它默認關閉。

自定義事務工廠:需實現TransactionFactory接口

自定義了事務工廠,還需通過實現Transaction接口,自定義事務類,就能夠通過自定義事務規則,滿足需要。

 

environment數據源環境:

存在三個數據源工廠:

PooledDataSourceFactory、UnpooledDataSourceFactory、JndiDataSourceFactory。

JndiDataSourceFactory會根據JNDI的信息,拿到外部容器實現的數據庫連接對象。

三個數據源工廠,最後生成的產品都會是一個實現了DataSource接口的數據庫連接對象。

UNPOOLED:採用非數據庫池的管理方式,每次請求都會打開一個新的數據庫連接,所以創建比較慢。傳遞屬性給數據庫驅動是個可選項,且屬性的前綴爲“driver”。

POOLED:利用“池”的概念將JDBC的Connection對象組織起來,省去了創建新的連接實例時的初始化和認證時間。

JNDI:爲了能在如EJB或應用服務器這類容器中使用,容器可以集中或在外部配置數據源,然後放置一個JNDI上下文的引用。

該數據源有兩個屬性可配置:

initial_context:用來在InitialContext中尋找上下文,如initialContext.lookup(initial_context)。

data_source:引用數據源實例位置上下文的路徑。

可通過添加前綴“env.”直接把屬性傳遞給初始化上下文InitialContext。

MyBatis也支持第三方數據源,例如使用DBCP數據源,則需提供一個自定義DataSourceFactory:

在配置文件中,進行相應的配置:

 

databaseIdProvider數據庫廠商標識:

使用系統默認的databaseIdProvider:

name是數據庫名稱,可通過connection.getMetaData().getDatabaseProductName()獲取。

value是一個別名,可在mapper文件中,標識一條SQL語句適用於哪種數據庫。

當databaseIdProvider屬性被配置時,系統會優先取到和數據庫配置一致的SQL,若沒有databaseId的SQL,則把它當作默認值。如果還是取不到,則會拋出異常。

 

不使用系統規則:

自定義DatabaseIdProvider:

public class MyDatabaseIdProvider implements DatabaseIdProvider {

	private static final String DATEBASE_TYPE_DB2 = "DB2";
	private static final String DATEBASE_TYPE_MYSQL = "MySQL";
	private static final String DATEBASE_TYPE_ORACLE = "Oralce";

	private Logger log = Logger.getLogger(MyDatabaseIdProvider.class);

	@Override
	public void setProperties(Properties props) {
		log.info(props);
	}

	@Override
	public String getDatabaseId(DataSource dataSource) throws SQLException {
		Connection connection = dataSource.getConnection();
		String dbProductName = connection.getMetaData().getDatabaseProductName();
		if (MyDatabaseIdProvider.DATEBASE_TYPE_DB2.equals(dbProductName)) {
			return "db2";
		} else if (MyDatabaseIdProvider.DATEBASE_TYPE_MYSQL
				.equals(dbProductName)) {
			return "mysql";
		} else if (MyDatabaseIdProvider.DATEBASE_TYPE_ORACLE
				.equals(dbProductName)) {
			return "oracle";
		} else {
			return null;
		}
	}
}

setProperties方法可以讀取配置的參數;getDatabaseId方法的返回值,返回去配置相應的SQL語句。

 

引入映射器的方法:

用文件路徑引入:

用包名引入:

用類註冊引入:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章