The Sqlsessionfactorybean (upper) _java of refactoring mybatis and spring integration in simple and simple

Source: Internet
Author: User
Tags inheritance xmlns

In general, the source code to modify the framework is extremely risky, unless you have to, otherwise do not modify. But today, it is carefully reconstructed mybatis officially provided with spring integration of the Sqlsessionfactorybean class, one is to hold the mentality of trial and error, and indeed there is a real need.

Let me explain two points:

In general, refactoring is the optimization of code without changing functionality, but the refactoring described in this article also includes adding functionality

The main jar packs used in this article (version): Spring-*-4.3.3.release.jar, Mybatis-3.4.1.jar, Mybatis-spring-1.3.0.jar

Here's a talk from MyBatis and spring integration.

I. Integrated MyBatis and Spring

<bean id= "Sqlsessionfactory" p:datasource-ref= "DataSource" class= "Org.mybatis.spring.SqlSessionFactoryBean" P: configlocation= "Classpath:mybatis/mybatis-config.xml" >
<property name= "Mapperlocations" >
< array>
<value>classpath*:* */*.sqlmapper.xml</value>
</array>
</property >
</bean>

The key class for integration is Org.mybatis.spring.SqlSessionFactoryBean, a factory bean used to produce MyBatis global Session factory Sqlsessionfactory (that is, factory beans that generate session factories), and sqlsess Ionfactory is used to generate session sqlsession objects (sqlsessionfactory equivalent to datasource,sqlsession equivalent to connection).

Where properties (configured using the P namespace or property child element):

DataSource is a data source that can be configured using DBCP, C3P0, Druid, Jndi-lookup, and many other ways

Configlocation is the global configuration of the MyBatis engine to modify the behavior of MyBatis

Mapperlocations is the sqlmapper script configuration file (schema) that MyBatis needs to load.

There are, of course, a lot of other properties here, not one by one examples.

Second, why to reconstruct

1, source optimization

Sqlsessionfactorybean's role is to produce sqlsessionfactory, let's take a look at this method (Sqlsessionfactorybean.java 384-538 lines):/** * Build a {@code
Sqlsessionfactory} instance. * * The default implementation uses the standard MyBatis {@code Xmlconfigbuilder} API to build a * {@code sqlsessionfactor
Y} instance based on a Reader.
* Since 1.3.0, it can be specified a {@link Configuration} instance directly (without config file). * * @return Sqlsessionfactory * @throws ioexception If loading the config file failed/protected build
Sqlsessionfactory () throws IOException {Configuration Configuration;
Xmlconfigbuilder xmlconfigbuilder = null; if (this.configuration!= null) {configuration = this.configuration; if (configuration.getvariables () = null) {Configur
Ation.setvariables (this.configurationproperties);  else if (this.configurationproperties!= null) {Configuration.getvariables (). Putall (This.configurationproperties);}} else if (this.configlocation!= null) {Xmlconfigbuilder = new XmlconfigbuIlder (This.configLocation.getInputStream (), NULL, this.configurationproperties);
Configuration = Xmlconfigbuilder.getconfiguration (); else {if (logger.isdebugenabled ()) {Logger.debug ("Property ' configuration ' or ' configlocation ' not specified, using de
Fault MyBatis Configuration ");
} Configuration = new configuration ();
Configuration.setvariables (this.configurationproperties); } if (this.objectfactory!= null) {configuration.setobjectfactory (this.objectfactory);} if (this.objectwrapperfactory
!= null) {configuration.setobjectwrapperfactory (this.objectwrapperfactory);} if (This.vfs!= null) {
Configuration.setvfsimpl (THIS.VFS); } if (Haslength (this.typealiasespackage)) {string[] Typealiaspackagearray = Tokenizetostringarray (
This.typealiasespackage, configurableapplicationcontext.config_location_delimiters); for (String Packagetoscan:typealiaspackagearray) {configuration.gettypealiasregistry (). Registeraliases ( Packagetoscan, Typealiasessupertype = null? Object.class:typeAlIasessupertype);
if (logger.isdebugenabled ()) {Logger.debug ("scanned package: ' + Packagetoscan +" ' for aliases ');}}
if (!isempty (this.typealiases)) {for (class<?> typeAlias:this.typeAliases) {
Configuration.gettypealiasregistry (). Registeralias (Typealias);
if (logger.isdebugenabled ()) {Logger.debug ("registered type alias: ' + Typealias + '");}} if (!isempty (This.plugins)) {for (Interceptor Plugin:this.plugins) {configuration.addinterceptor (plugin); if (LOGGER.
Isdebugenabled ()) {logger.debug ("Registered plugin:" + plugin + "');}}} if (Haslength (this.typehandlerspackage)) {string[] Typehandlerspackagearray = Tokenizetostringarray (
This.typehandlerspackage, configurableapplicationcontext.config_location_delimiters); for (String Packagetoscan:typehandlerspackagearray) {configuration.gettypehandlerregistry (). Register (
Packagetoscan);
if (logger.isdebugenabled ()) {Logger.debug ("scanned Package:" + Packagetoscan + "' for type Handlers");}} if (!isempTy (this.typehandlers)) {for (typehandler<?> typeHandler:this.typeHandlers) {
Configuration.gettypehandlerregistry (). Register (Typehandler);
if (logger.isdebugenabled ()) {Logger.debug ("registered type handler:" + Typehandler + "");}} if (This.databaseidprovider!= null) {//fix #64 set databaseId before parse mapper xmls try {Configuration.setdatabaseid (
This.databaseIdProvider.getDatabaseId (This.datasource));
catch (SQLException e) {throw new Nestedioexception ("Failed getting a DatabaseId", e);} if (This.cache!= null) {Configuration.addcache (this.cache);} if (Xmlconfigbuilder!= null) {try {Xmlconfigbuilder.par
SE (); if (logger.isdebugenabled ()) {Logger.debug ("Parsed configuration file:" + this.configlocation + "");} catch (Exception ex) {throw new Nestedioexception ("Failed to parse Config resource:" + This.configlocation, ex);}
finally {errorcontext.instance (). reset (); if (this.transactionfactory = = null) {this.transactionfactory = new SpringmaNagedtransactionfactory ();
} configuration.setenvironment (new Environment (This.environment, This.transactionfactory, This.dataSource)); 
if (!isempty (this.mapperlocations)) {for (Resource mapperLocation:this.mapperLocations) {if (mapperlocation = null) {
Continue try {xmlmapperbuilder Xmlmapperbuilder = new Xmlmapperbuilder (Mapperlocation.getinputstream (), Configuration,
Mapperlocation.tostring (), configuration.getsqlfragments ());
Xmlmapperbuilder.parse (); catch (Exception e) {throw new Nestedioexception ("Failed to parse Mapping resource: '" + mapperlocation + "'", e);} finally {errorcontext.instance (). reset ();} if (logger.isdebugenabled ()) {Logger.debug ("parsed mapper file: '" + Mapperl ocation + "'");}} else {if (logger.isdebugenabled ()) {Logger.debug ("Property ' Mapperlocations ' is not specified or no matching)
Found ");
} return This.sqlSessionFactoryBuilder.build (configuration); }

Although MyBatis is an excellent persistence layer framework, it is true that this code is really not good, there is a lot of refactoring optimization space.

2, Function expansion

(1) using schema to verify Sqlmapper

<!--DTD way-->
<?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= "Org.dysd.dao.mybatis.config.IExampleDao" >
</mapper>
<!--schema mode-- >
<?xml version= "1.0" encoding= "UTF-8"?> <mapper xmlns:xsi=
"http://www.w3.org/2001/" Xmlschema-instance " 
xmlns=" Http://dysd.org/schema/sqlmapper "
xsi:schemalocation=" http://dysd.org/ Schema/sqlmapper http://dysd.org/schema/sqlmapper.xsd "
namespace=" Org.dysd.dao.mybatis.config.IExampleDao " >
</mapper>

It may seem more complicated to use a schema at first, but with the IDE, the automatic hints for schema are friendlier, the checksum is clearer, and a window opens for other developers, allowing them to customize namespaces on the basis of existing namespaces, such as introducing <OGNL > tags, using OGNL expressions to configure SQL statements, and so on.

(2) Custom configuration, Sqlsessionfactorybean has provided more parameters for custom configuration, but it is still possible to require more personalized settings, such as:

A, the default result type is set, and for <select> elements that do not have Resulttype and Resultmap set, the default return type for the resolution can be set to map to simplify the configuration of Sqlmapper

<!--simplification before-->
<select id= "select" resulttype= "Map" >
SELECT * FROM table_name WHERE FIELD1 = #{field1, Jdbctype=varchar} 
</select>
<!--simplified-->
<select id= "Select" >
select * from Table_ NAME WHERE FIELD1 = #{field1, Jdbctype=varchar} 
</select>

B, extended mybatis original parameter parsing, native resolution implementation is Defaultparameterhandler, can inherit and extend this implementation, such as for Spel: The prefix of the property expression, using Spel to evaluate

(3) Other extensions may refer to the author's previous blog about MyBatis expansion

3. Reconstruction Feasibility

(1) in the scope of the code impact

The following is the inheritance structure of the Sqlsessionfactorybean

As you can see, the Sqlsessionfactorybean inheritance system is not complex and does not inherit other parent classes, but implements the three interfaces in spring (EventListener in JDK is just an identity). And Sqlsessionfactorybean is for the end user, there are no subclasses, and no other classes call it, so it's very small from the scope of the code impact.

(2) In the refactoring implementation, you can create a new Schemasqlsessionfactorybean, and then a start code completely copy Sqlsessionfactorybean, modify the package name, class name, and then as the basis for refactoring, this is relatively simple.

(3) In integrated applications, only the class attribute in the spring integration configuration needs to be modified.

The above is a small series to introduce the refactoring MyBatis and spring integration of the Sqlsessionfactorybean (on), I hope to help you, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.