In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
Author: wuxinliulei
Link: https://www.zhihu.com/question/25007334/answer/266187562
Source: Zhihu
The copyright belongs to the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.
Mybatis, formerly known as Ibatis, upgraded from Ibatis2.x to Mybatis 3.x in 2011, and moved the project address from Apache to Google code. In fact, we see that the class full path name of MyBatis still retains the package prefixes of Apache and Ibatis.
Import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder
However, the configuration file, operation class and implementation of MyBatis have changed a lot. Here we focus on Mybatis, not Ibatis.
There are two types of configuration files for Mybatis:
One is used to specify data sources, transaction attributes, and other parameter configuration information (usually a separate file, which can be called a global configuration file).
The other is used to specify mapping information between database tables and programs (there may be more than one file, which we call a mapping file).
There is no definite requirement for the names of these files; it's just that the xml document constraint most from a specific dtd, that is, the xml tag needs to meet the requirements.
This is the data source, transaction properties, and index of the mapping file for MyBatis.
Select * from users where id=# {id}
Above is the mapping file between the database table and the program, defining a sql to obtain User objects according to id
The entity class corresponding to the package com.test.domain;/** * users table * / public class User {/ / the attribute of the entity class and the field name of the table correspond one to one to private int id; private String name; private int age; public int getId () {return id;} public void setId (int id) {this.id = id;} public String getName () {return name } public void setName (String name) {this.name = name;} public int getAge () {return age;} public void setAge (int age) {this.age = age;} @ Override public String toString () {return "User [id=" + id + ", name=" + name + ", age=" + age + "]";}}
Question:
How does mybatis successfully find sqlmapper in the program? what is the process of this?
/ / mybatis's configuration file String resource = "conf.xml"; / / use the classloader to load the mybatis's configuration file (which also loads the associated mapping file) InputStream is = Test1.class.getClassLoader (). GetResourceAsStream (resource); / / build sqlSession factory SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder (). Build (is)
The sqlmapper of the question can be understood as two components, one is the mapping mapping file, which obtains the corresponding sql statement through the id name and manipulates the database, and the other is the return object of sql
ResultType= "com.test.domain.User"
This is where the returned sql result is mapped to a concrete POJO (Plain Ordinary Java Object) object.
Two important classes are:
Org.apache.ibatis.session.SqlSessionFactory
Org.apache.ibatis.session.SqlSession
Package org.apache.ibatis.session;import java.sql.Connection;public interface SqlSessionFactory {SqlSession openSession (); SqlSession openSession (boolean autoCommit); SqlSession openSession (Connection connection); SqlSession openSession (TransactionIsolationLevel level); SqlSession openSession (ExecutorType execType); SqlSession openSession (ExecutorType execType, boolean autoCommit); SqlSession openSession (ExecutorType execType, TransactionIsolationLevel level); SqlSession openSession (ExecutorType execType, Connection connection); Configuration getConfiguration ();}
When you build the SqlSessionFactory class, the data source and transaction configuration will be parsed, as specified in the
Org.apache.ibatis.builder.xml.XMLConfigBuilder class
Org.apache.ibatis.builder.BaseBuilder class
The XMLConfigBuilder class is the concrete class that parses the org.apache.ibatis.Session.Configuration class, and all the configurations in the Configuration class will be saved.
Source code analysis of mybatis (1)-- xml file analysis-Wang Jiuyong-blog Garden
This blog introduces some basics of xml file parsing
XPath is used in xml parsing of specific mybatis. For more information on the parsing process, please see
Https:// zhuanlan.zhihu.com/p/31 418285
In fact, all kinds of wheels generally have a special storage class for parsing the information after XML, such as Config.Java,xxxConf.java, which parses the XML configuration for use in the program when starting the component.
Quote a piece of source code on the network
Public class Test1 {public static void main (String [] args) throws IOException {/ / mybatis configuration file String resource = "conf.xml"; / / use the classloader to load the configuration file of mybatis (which also loads the associated mapping file) InputStream is = Test1.class.getClassLoader (). GetResourceAsStream (resource); / / build sqlSession factory SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder (). Build (is) / / use the Resources class provided by MyBatis to load the configuration file of mybatis (which also loads the associated mapping file) / / Reader reader = Resources.getResourceAsReader (resource); / / build the factory of sqlSession / / SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder (). Build (reader); / / create sqlSession SqlSession session = sessionFactory.openSession () that can execute sql in the mapping file / * Mapping the identity string of sql, * me.gacl.mapping.userMapper is the value of the namespace attribute of the mapper tag in the userMapper.xml file, and * getUser is the id attribute value of the select tag. The SQL * / String statement = "me.gacl.mapping.userMapper.getUser" to be executed can be found through the value of the id attribute of the select tag. / / Mapping the identity string of sql / / execute the query to return sql User user = session.selectOne (statement, 1) of a unique user object; System.out.println (user);}}
By tracking the source code, you can see how SqlSession finds data through the id mapped by mapper.
Org.apache.ibatis.session.defaults.DefaultSqlSession class
Public List selectList (String statement, Object parameter, RowBounds rowBounds) {try {MappedStatement ms = configuration.getMappedStatement (statement); List result = executor. Query (ms, wrapCollection (parameter), rowBounds, Executor.NO_RESULT_HANDLER); return result;} catch (Exception e) {throw ExceptionFactory.wrapException ("Error querying database. Cause:" + e, e);} finally {ErrorContext.instance (). Reset ();}}
Org.apache.ibatis.session.Configuration class
Public MappedStatement getMappedStatement (String id) {return this.getMappedStatement (id, true);}
Protected final Map mappedStatements = new StrictMap ("Mapped Statements collection")
Public MappedStatement getMappedStatement (String id, boolean validateIncompleteStatements) {if (validateIncompleteStatements) {buildAllStatements ();} return mappedStatements.get (id);}
In fact, it is based on a map mapping, and key is obtained by defining the id of mapping.
So far
-
The executor object in the selectList method of the above org.apache.ibatis.session.defaults.DefaultSqlSession class object
By default, when the cache and executor properties of settings are not set, the default
Org.apache.ibatis.executor.CachingExecutor class
Public Executor newExecutor (Transaction transaction, ExecutorType executorType, boolean autoCommit) {executorType = executorType = = null? DefaultExecutorType: executorType; executorType = executorType = = null? ExecutorType.SIMPLE: executorType; Executor executor; if (ExecutorType.BATCH = = executorType) {executor = new BatchExecutor (this, transaction);} else if (ExecutorType.REUSE = = executorType) {executor = new ReuseExecutor (this, transaction) } else {executor = new SimpleExecutor (this, transaction);} if (cacheEnabled) {executor = new CachingExecutor (executor, autoCommit);} executor = (Executor) interceptorChain.pluginAll (executor) Return executor;}
So it was called.
Public List query (MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {BoundSql boundSql = ms.getBoundSql (parameterObject); CacheKey key = createCacheKey (ms, parameterObject, rowBounds, boundSql); return query (ms, parameterObject, rowBounds, resultHandler, key, boundSql);}
When querying cache first, you can see that the cache level is on MappedStatement, that is, on a single Sql. If it is found, it will be returned directly. If not, it will be queried through jdbc, and the result will be returned.
Public List query (MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {Cache cache = ms.getCache (); if (cache! = null) {flushCacheIfRequired (ms); if (ms.isUseCache () & & resultHandler = = null) {ensureNoOutParams (ms, key, parameterObject, boundSql) If (! dirty) {cache.getReadWriteLock () .readLock () .lock () Try {@ SuppressWarnings ("unchecked") List cachedList = (List) cache.getObject (key) If (cachedList! = null) return cachedList } finally {cache.getReadWriteLock () .readLock () .unlock ();}} List list = delegate. Query (ms, parameterObject, rowBounds, resultHandler, key, boundSql); tcm.putObject (cache, key, list); / / issue # 578. Query must be / / not synchronized to / / prevent deadlocks return list }} return delegate. Query (ms, parameterObject, rowBounds, resultHandler, key, boundSql);}
The above use is in a way that does not use an agent, which requires us to openSession ourselves and close Session
SqlSession session = null;try {session = sessionFactory.openSession (); / * maps the identity string of sql, and com.test.mapping.userMapper is userMapper. * the value of the namespace attribute of the mapper tag in the xml file. * getUser is the id attribute value of the select tag. The SQL * / String statement = "com.test.mapping.userMapper.getUser" to be executed can be found through the id attribute value of the select tag; / / the identity string of sql is mapped / / the query returns the sql User user = session.selectOne (statement, 1) of a unique user object. System.out.println (user);} catch (Exception e) {/ / TODO: handle exception} finally {if (session! = null) {session.close ();}}
In fact, if we use SqlSessionManager to manage, then we don't have to deal with turning on and off Session.
Final SqlSessionManager sqlSessionManager = SqlSessionManager.newInstance (sessionFactory); String statement = "com.test.mapping.userMapper.getUser"; / / Mapping sql identity string User user = sqlSessionManager.selectOne (statement, 1); System.out.println (user)
The following is the Interceptor class implementation, where both the open and close operations are left to
Private class SqlSessionInterceptor implements InvocationHandler {public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get (); if (sqlSession! = null) {try {return method.invoke (sqlSession, args) } catch (Throwable t) {throw ExceptionUtil.unwrapThrowable (t);}} else {final SqlSession autoSqlSession = openSession () Try {final Object result = method.invoke (autoSqlSession, args); autoSqlSession.commit (); return result } catch (Throwable t) {autoSqlSession.rollback (); throw ExceptionUtil.unwrapThrowable (t) } finally {autoSqlSession.close ();}}
If we use Mapper to operate SQL, we can use dynamic proxy to avoid our handwritten id string of mapper, and put the process of finding sql and executing sql into the agent processing, which is more elegant, but this is the general flow, which changes the steps of finding sql. We can find the corresponding sql through the method name of Mapper.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.