Mybatis实现【1】 ---Mybatis Basic[Java persistence with MyBatis3]

 Why Mybatis

-It Eliminates a lot of JDBC boilerplate code

  --MyBatis provides many other features that simplify the implementation of persistence logic

        ---It supports the mapping of complex SQL result set data to nested object graph structures

        ---It supports the mapping of one-to-one and one-to-many results to Java objects

        ---It supports building dynamic SQL queries based on the input data

-It has a low learning curve

-It works well with legacy databases

-It embraces SQL

-It provides support for integeration with Spring and Guice frameworks

-It porvides support for integeration with third-party cache libraries

-It induces better performance

        --MyBatis supports database connection pooling that eliminates the cost of creating a database connection on demand for every request.

        --Mybatis has an in-built cache mechanism which caches the results of SQL queries at the SqlSession level. That is, if you invoke the same mapped select query , then MyBatis returns the cached result instead of querying the database again.

        --MyBatis doesn't use proxying heavily and hence yields better performance compared to other ORM frameworks that use proxies extensively.


Best Practice

  1. -There should be only one instance of SqlSessionFactory per database environment , so we have used a singleton pattern to have only one instance of SqlSessionFactory.

  2. -Instances of SqlSession objects are not thread safe and should not be shared.So the best scope for SqlSession is the method scope.From a web application perpective,SqlSession should have a request scope.



Configuration MyBatis using XML

Environment:

If your application needs to connect to multiple database, you'll need to configure each database as a separate environment and create a separate SqlSessionFactory object for each other.

麦库截图20141005100512575.jpg 

DataSource:

The dataSource type can be one of the built-in types sucn as 'UNPOOLED','POOLED','JNDI'

-If you set the type to UNPOOLED,MyBatis will open a new connection and close that connection for every database operation. This method can be used for simple applications that have a small number of concurrent users.

-If you set the type to POOLED,MyBatis will create a pool of database connections,and one of these conncetions will be used for the database operation.Once this is complete,MyBatis will return the connection to the pool.This is a commonly used method for developing/testing environment.

-If you set the type to JNDI,MyBatis will get the connection from the JNDI dataSource that has typically been configured in the application server.

TransactionManager

MyBatis supports two types of transaction managers:JDBC and MANAGED

-The JDBC transaction manager is used where the application is responsible for managing the connection life cycle,that is,commit,rollback,and so on.When you set the TransactionManager property to JDBC,behind the scenes MyBatis uses the JdbcTransactionFactory class to create TransactionManager.For example,an application deployed onApache Tomcat should manage the transactions by itself.

-The MANAGED transaction manager is used where the application server is responsible for managing the connection life cycle.When you set the TransactionManager property to MANAGED,behind the scenes MyBatis used the ManagedTransactionFactory class to create TransactionManager.For example,a JavaEE application deployed on anserver,such as JBoss,WebLogic,or GlassFish,can leverage the application server's transaction management capabilities using EJB.In these managed environments,you can use the MANAGED transaction manager.

typeAliases

Instead of typing the fully qualified names everywhere, we can give the alias names and use these alias names in all the other places where we need to give the fully qualified names.

麦库截图20141005105541667.jpg 
you can also give the package name where MyBatis can scan and register aliases using uncapitalized nonqualifiedcalss names of the bean.

There is another way of aliasing JavaBeans , using the @Alias annotation

麦库截图20141005105740998.jpg 
The @Alias annotation overrides the <typeAliases> configuration.

typeHandlers

To let MyBatis understand how to handle custom Java object types,we can extend abstract class BaseTypeHandler<T> to create custom type handlers.

Once the custom type handler is implemented , we need to register it in mybatis-comfig.xml

麦库截图20141105111234998.jpg 

Settings

The default MyBatis global setting, which can be overridden to better suit application-specific needs,are as fllows:

麦库截图20141105112002601.jpg 
Mappers

We need to configure the locations of the SQL Mapper files mybatis-config.xml

麦库截图20141105112501849.jpg 
-The attribute resource can be used to point to a mapper file that is in the classpath

-The attribute url can be used to point to a mapper file by its fully qualified filesystem path or web URL

-The attribute class can be used to point to a Mapper interface

-The package element can be used to point to a package name where Mapper interfaces can be found.

Customizing MyBatis logging

MyBatis uses its internal LoggerFactory as a facade to actual logging libraries.The internal LoggerFactory will delegate the logging task to one of the following actual logger implementations,with the priority decreasing from top to buttom in the given order:

麦库截图20141105115336301.jpg 

If MyBatis finds none of ther previous implementations , logging will be disabled.

You also can make MyBatis to use a specific logging implementation.


 Mapper XMLs and Mapper interfaces

Autogenerated keys

We can use the useGeneratedKeys and keyProperty attributes to let the database generate the auto_increment column value and set that generated value into one of the input object properties as follows:

麦库截图20141505150005821.jpg 

Here the STUD_ID column value will be autogenerated by MySQL database,and the generated value will be set to the studId property of the student object.

Some databases such as Oracle dont't support AUTO_INCREMENT columns and use SEQUENCE to generated th primary key values.

麦库截图20141505150412185.jpg 

麦库截图20141505150429289.jpg 

Here we used the <selectKey> subelement to generate the primary key value and stored it in the studId property of the Student object.The attribute order='BEFORE' indicates that MyBatis will get the primary key value,that is,the next value from the sequence and store it in the studId property before executing the INSERT query.[Like ORACLE]

We can also set the primary key value using a trigger where we will obtain the next value from the sequence and set it as the primary key column value before executing the INSERT query.[LIKE MYSQL]

麦库截图20141505150904404.jpg 

Simple ResultMaps

麦库截图20141505153621469.jpg 

resultMap can be a map type(we will get a  Map<key_column,Object>)

麦库截图20141505153719091.jpg 

or we will get List<HashMap<key_column,Object>> 

麦库截图20141505153840523.jpg 

Extending ResultMaps

We can extends one <resultMap> query from another <resultMap> query,thereby inheriting the column to do property mappings from the one that is being extended.

 麦库截图20141505154208564.jpg 

One-to-one mapping

  1. We can set the properties of a nested object using the dot notation

麦库截图20141605162223812.jpg 

2.The <association>element can be used to load the has-one type of association.In the preceding eample,we usedthe <association>element,referencing another <resultMap> that is declared in the same XML flee

麦库截图20141605162441465.jpg 

We can also use <association> with an inline resultMap query as follows:

麦库截图20141605162613090.jpg 

Using the nested ResultMap approach , the association data will be loaded using a single query(along with joins ifrequired)

3.One-to-one mapping using nested Select

麦库截图20141605163248999.jpg 

麦库截图20141605163302377.jpg 

One-to-many mapping

1、One-to-many mapping with nested ResultMap

麦库截图20141605164519215.jpg 

麦库截图20141605164533082.jpg 

2.One-to-many mapping with nested select

麦库截图20141605165356765.jpg 

麦库截图20141605165411553.jpg 

A nested select approach may result in N+1 select problems.First, the main query will be excuted(1),and for every row returned by the first query,another select query will be executed(N queries for N rows).For large datasets,this could result in poor performance.

Dynamic SQL

  1. The If condition

麦库截图20141705173726905.jpg 

麦库截图20141705173737652.jpg 

2.The choose,when,and otherwise conditions

--MyBatis evaluates the <choose> test conditions and uses the clause with the first condition that evaluates to TRUE.If none of the conditions are true,the <otherwise> clause will be used.

麦库截图20141705174247304.jpg 

3.The<where>element inserts WHERE only if any content is returned by the inner conditional tags.Also,it removes the AND or OR prefixs if the WHERE clause begins with AND or OR.

麦库截图20141705175224938.jpg 

麦库截图20141705175302626.jpg 

4.The <trim>element works similar to <where> but provides additional flexibility on what prefix/suffix needs to be prefixed/suffixed and what prefix/suffix needs to be stripped off.

麦库截图20141705175800618.jpg 

Here <trim> will insert WHERE if any of the <if> conditions are true and remove the AND or OR prefixes just after WHERE.

5.The foreach loop

麦库截图20141805180503996.jpg

6.The set condition

The <set> element is similar to the <where> element and will insert SET if any content is returned by the inner conditions.

麦库截图20141805181258471.jpg 

Here,<set>inserts the SET keyword if any of the <if> conditions return text and also strips out the tailing commas at the end.

MyBatis Recipes

Handling enumeration types

By default,MyBatis uses EnumTypeHandler to handle enum type Java properties and stores the name of the enum value.You don't need any extra configuration to do this.You can use enum type properties just like primitive type properties.

If you want to store the ordinal position of the enum instead of the enum name,you will need to explicitly configure it.You'll to register EnumOrdinalTypeHandler in the mybatis-config.xml file.

麦库截图20141106115503621.jpg 

[Be careful to use ordinal values to store in the DB.Ordinal values are assigned to enum values based on their order of declaration. If you change the declaration order in enum,the data in the database and ordinal values will be mismatched]

Handling the CLOB/BLOB types

By default, MyBatis maps CLOB type columns to the java.lang.String type and BLOB type columns to the byte[] type.

麦库截图20141306133905152.jpg to麦库截图20141306133918248.jpg 

Passing multiple input parameters

  1. We can put all the input parameters in a HashMap and pass it to that mapped statement.

  2. MyBatis provides another way of passing multiple input parameters to a mapped statement.

MyBatis supports passing multiple input parameters to a mapped statement and referencing them using the ${param} syntax.

麦库截图20141306134954748.jpg 

Here #{param1} refers to the first parameter and #{param2} refers to the second parameter 

麦库截图20141306135108479.jpg 

Multiple results as a map

If we have a mapped statement that returns multiple rows and we want the results in a HashMap with some property value as the key and the resulting object as the value,we can use sqlsession.selectMap() as fllows:

麦库截图20141306135442510.jpg 

Here studentMap will contain studId values as keys and Student objects as values.

Paginated ResultSets using RowBounds

MyBatis can load table data page by page using RowBounds.The RowBounds object can be constructed using th offset and limit parameters.The parameter offset refers to the starting position and limit refers to the number of records.

麦库截图20141406140001645.jpg 

To display the second page,use offset=25 and limit=25;for third page,use offset=50 and limit=25

Custom ResultSet processing using ResultSetHandler

MyBatis provides ResultHandler plugin that enables the processing of the ResultSet in whatever way we like.

麦库截图20141406140657334.jpg 

As the handleResult() method will be called for every row returned by the query,we are extracting the studId and name values from the Student object and populating the map.

Cache

By default,the first-level cache is enabled;this means that if you'll invoke the same SELECT statement within the same sqlSession interface,results will be fetched from the cache instead of the database.

We can add global second-level cacahes by adding the <cache/> element in SQL Mapper XML files.

When you'll add the <cache/> element the following will occur:

  • All results from the <select> statements in the mapped statement file will be cached

  • All the <insert>、<update>、and <delete> statements in the mapped statement file will flush the cache.

  • The cache will use a Least Recently Used(LRU) algorithm for eviction

  • The cache will not flush on any sort of time-based schedule(no Flush Interval)

  • The cache will store 1024 references to lists or objects(whatever the query method returns)

  • The cache will be treated as a read/write;this means that the objects retrieved will not be shared and can safely be modified by the caller without it interfering with other potential modifications by other callers or threads

You can also customize this behavior by overriding the default attribute values as follows:

麦库截图20141406143815805.jpg 

A description for each of the attributes is as follow:

麦库截图20141406143907587.jpg 

A cache configuration and cache instance are bound to the namespaces of the SQL Mapper file,so all the statements in the same namespace table as the cache are bound 

The default cache configuration for a mapped statement is :

麦库截图20141406144238327.jpg 

You can override this default behavior for any specific mapped statements;for example , by not using a chache for a select staement by setting the useCache='false" attribute.

In addition to in-built Cache support,MyBatis provides support for integration with popular third-party Cache libraries,such as Ehcache,OSCache,and Hazelcast.

SQL Mappers Using Annotations

@Insert

1.We can use the useGeneratedKeys and keyProperty attributes of the @Options annotation to let the database server generate the auto_increment column value and set that generated value as one of the input object properties.

麦库截图20140708071251200.jpg 

Here the STUD_ID column value will be autogenerated by MySQL database and the generated value will be set to the studId property of the student object.

2.We can use the @SelectKey annotation to specify any SQL statement that will give the primary key value , which can be used as the primary key column value

麦库截图20140708071642904.jpg 

Here we have used @SelectKey to generate the primary key value and store it in the studId property of the Student object using the keyProperty attribute. This gets executed before executing the INSERT statement,because we specified it via the before=true attribute.[Oracle]

If we are setting the primary key value through triggers using SEQUENCE, we can obtain the database-generated primary key value from sequence_name.vurrval after the INSERT statement is executed.[MySQL]

麦库截图20140708072113356.jpg 

Result maps

1.We can map query results to JavaBean properties using inline aliases or using an explict @Result annotation.

麦库截图20140708073645211.jpg 

麦库截图20140708073657387.jpg 

The @Result annotation is a couterpart of the Mapper XML element <resultMap>.However,as of MyBatis3.2.2 we can't give an ID for the @Result annotation.So unlike the <resultMap> XML element,we can't reuse the @Results declaration across different mapped statements.What this means is that you need to duplicate the @Results configuration even though it is the same.

麦库截图20140708074123246.jpg 

Here the @Results configuration is same for both the statements,but we need to duplicate it.There is also a work around for this problem.We can create a Mapper XML file and configure the <resultMap>element and reference that resultMap using the @ResultMap annotation.

麦库截图20140708074411023.jpg 

麦库截图20140708074509879.jpg 

One-to-one mapping

1.MyBatis provides the @one annotation to load a one-to-one association using a Nested-Select statement

麦库截图20140808084644906.jpg 

2.we can load a one-to-one association using nested ResultMap using XML-base Mapper configuration.But as of MyBatis-3.2.2,there is no annotation-based counterpart for this kind of mapping.However,we can define <resultMap> in Mapper XML file and reference it

麦库截图20140808085018170.jpg 

One-to-many mapping

1.MyBatis provides the @many annotation to load a one-to-many association using a Nested-Select statement.

麦库截图20140808085622435.jpg 

2.Using an XML-based Mapper configuration , we can load a one-to-many association using a nested ResultMap.As of MyBatis 3.2.2,there is no annotation-based counterpart for this kind of mapping.But we can define the <resultmap> in the Mapper XML file and reference it using the @ResultMap annotaion.

麦库截图20140808085917140.jpg 

麦库截图20140808085928283.jpg 

Dynamic SQL

Sometimes we may need to build queries dynamically based on input criteria.MyBatis provides various annotations such as @InsertProvider,@UpdateProvider,@DeleteProvider,and @SelectProvider,which facilitates building dynamic queries and lets MyBatis execute those queries.

  1. @SelectProvider

The SQL utility providers various methods to perform JOINS,ORDER_BY,GROUP_BY,and so on

麦库截图20140908094819252.jpg 

麦库截图20140908094836289.jpg 

2.@InsertProvider

麦库截图20140908094930097.jpg 

3.@UpdateProvider

麦库截图20140908095005601.jpg 

4.@DeleteProvider

麦库截图20140908095030338.jpg 

麦库截图20140908095048572.jpg 

该系列文章参考如下书籍及文章:

《Java Persistence with MyBatis 》

《http://www.cnblogs.com/hzhuxin/p/3349836.html》

《http://www.iteye.com/topic/1112327》

《http://www.iteye.com/blogs/subjects/mybatis_internals》

《http://denger.me/2011/05/mybatis-and-spring-interface-integrated/》








































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值