最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mybatis3使用@Select等注解實(shí)現(xiàn)增刪改查操作

 更新時(shí)間:2020年11月30日 11:25:32   作者:ZJE_ANDY  
這篇文章主要介紹了mybatis3使用@Select等注解實(shí)現(xiàn)增刪改查操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

1.需要的jar包

2.目錄樹(shù)

3.具體代碼

一.需要的jar包

第一個(gè):mybatis的jar包

第二個(gè):mysql數(shù)據(jù)的驅(qū)動(dòng)

二.目錄樹(shù)

三.具體代碼

使用框架,配置文件先行!

conf.xml:(配置 登錄數(shù)據(jù)庫(kù),映射文件)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
 <environments default="mysql">
  <environment id="mysql">
  <transactionManager type="JDBC"/>
  <dataSource type="POOLED">
   <property name="driver" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
   <property name="username" value="root"/>
   <property name="password" value="zhujunwen"/>
  </dataSource> 
  </environment>
 </environments>
 
 <!-- 配置映射-->
 <mappers>
 <!-- 若映射文件mapper 是xml,則<mapper recourse...>,若映射文件為java文件,則<mapper class.....> -->
 <mapper class="com.UserMapper"/> 
 </mappers>
</configuration>

映射文件:

UserMapper.java:(用于映射SQL語(yǔ)句)

package com; 
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
public interface UserMapper {
 
 /*
 這個(gè)一個(gè)接口,但不需要實(shí)現(xiàn)它,用于 函數(shù)與SQL語(yǔ)句 的映射
 * */
 
 @Insert("insert into tb_user(name,sex) values(#{name},#{sex})")
 public void insertT(User user);
 
 @Delete("delete from tb_user where id=#{id}")
 public void deleteById(int id);
 
 @Update("update tb_user set name=#{name},sex=#{sex} where id=#{id}")
 public void updateT(User user);
 
 @Select("select * from tb_user where id=#{id}")
 public User getUser(int id);
 
 @Select("select * from tb_user")
 public List<User> getAllUsers();
}

持久類(lèi):

User.java:(持久類(lèi)中的成員變量要與數(shù)據(jù)表中的字段名字一致)

package com;
 
public class User {
 private Integer id;
 private String name;
 private String sex;
 public Integer getId() {
 return id;
 }
 public void setId(Integer id) {
 this.id = id;
 }
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public String getSex() {
 return sex;
 }
 public void setSex(String sex) {
 this.sex = sex;
 }
 
 public String toString() {
 return "User [id=" + id + ", name=" + name + ", sex=" + sex + "]";
 }
}

必要變量的快速獲?。海ǐ@取Session)

FKSqlSessionFactory.java:

package com; 
import java.io.IOException;
import java.io.InputStream; 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 
public class FKSqlSessionFactory {
 private static SqlSessionFactory sqlSessionFactory = null;
 static{
 InputStream input;
 try {
 input = Resources.getResourceAsStream("conf.xml");
 sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 }
 
 public static SqlSession getSqlSession(){
 return sqlSessionFactory.openSession();
 }
 
 public static SqlSessionFactory getSqlSessionFactory(){
 return sqlSessionFactory;
 }
}

測(cè)試文件(只是演示對(duì)數(shù)據(jù)庫(kù)的插入)

package com; 
import java.util.ArrayList;
import java.util.List; 
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
 
public class Test1 { 
 public static void main(String[] args) {
 SqlSessionFactory factory= FKSqlSessionFactory.getSqlSessionFactory();
 SqlSession session = factory.openSession();
 UserMapper mapper = session.getMapper(UserMapper.class);//獲取映射器實(shí)例
 
 User user = new User();
 user.setName("zhujunwen");
 user.setSex("m"); 
 mapper.insertT(user); //調(diào)用映射器中的insertT()方法進(jìn)行數(shù)據(jù)庫(kù)插入 
 session.commit();
 session.close();
 }
}

效果:

已有數(shù)據(jù)插入到數(shù)據(jù)表

數(shù)據(jù)表的樣式:

補(bǔ)充知識(shí):mybatis 一次select操作執(zhí)行流程分析

1.測(cè)試代碼

package com.testmybatis; 
import java.io.IOException;
import java.io.InputStream;
import java.util.List; 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger; 
import com.alibaba.fastjson.JSON;
import com.testmybatis.dao.TestMapper;
import com.testmybatis.model.Test;
 
public class testlanjie {
 
 private static Logger log=Logger.getLogger(testlanjie.class);
 
 public static void main(String args[]){
 List<Test> tests=null;
 try {
  String resource = "com/testmybatis/mybatis-config.xml";
  InputStream inputStream = Resources.getResourceAsStream(resource);
  SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  SqlSession session = sqlSessionFactory.openSession();
  try {
  TestMapper mapper=session.getMapper(TestMapper.class);
  tests=mapper.test();
  session.commit();
  } finally {
  session.close();
  }
 
 } catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 if(tests!=null)
  log.info(JSON.toJSONString(tests));
 }
 
}

2.流程分析

第一步構(gòu)造SqlSessionFactory

String resource = "com/testmybatis/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSessionFactoryBuilder下的build函數(shù)

public SqlSessionFactory build(InputStream inputStream) {
  return build(inputStream, null, null);
 }
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
   XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
   return build(parser.parse());
  } catch (Exception e) {
   throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  } finally {
   ErrorContext.instance().reset();
   try {
    inputStream.close();
   } catch (IOException e) {
    // Intentionally ignore. Prefer previous error.
   }
  }
 }
public SqlSessionFactory build(Configuration config) {
  return new DefaultSqlSessionFactory(config);
 }

先用配置文件的文件流對(duì)象構(gòu)造一個(gè)XMLConfigBuilder對(duì)象,在調(diào)用parse函數(shù)得到Configuration對(duì)象

public Configuration parse() {
  if (parsed) {
   throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed = true;
  parseConfiguration(parser.evalNode("/configuration"));
  return configuration;
 }
 
 private void parseConfiguration(XNode root) {
  try {
   Properties settings = settingsAsPropertiess(root.evalNode("settings"));
   //issue #117 read properties first
   propertiesElement(root.evalNode("properties"));
   loadCustomVfs(settings);
   typeAliasesElement(root.evalNode("typeAliases"));
   pluginElement(root.evalNode("plugins"));
   objectFactoryElement(root.evalNode("objectFactory"));
   objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
   reflectorFactoryElement(root.evalNode("reflectorFactory"));
   settingsElement(settings);
   // read it after objectFactory and objectWrapperFactory issue #631
   environmentsElement(root.evalNode("environments"));
   databaseIdProviderElement(root.evalNode("databaseIdProvider"));
   typeHandlerElement(root.evalNode("typeHandlers"));
   mapperElement(root.evalNode("mappers"));
  } catch (Exception e) {
   throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  }

其中mybatis主要的配置都在這里完成,存放在configuration中,本次分析會(huì)用到的兩個(gè)函數(shù)是environmentsElement和mapperElement,一個(gè)是構(gòu)造datasource,一個(gè)是構(gòu)造存放所有MapperProxyFactory的MapperRegistry,相應(yīng)的源代碼如下

private void environmentsElement(XNode context) throws Exception {
  if (context != null) {
   if (environment == null) {
    environment = context.getStringAttribute("default");
   }
   for (XNode child : context.getChildren()) {
    String id = child.getStringAttribute("id");
    if (isSpecifiedEnvironment(id)) {
     TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
     DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
     DataSource dataSource = dsFactory.getDataSource();
     Environment.Builder environmentBuilder = new Environment.Builder(id)
       .transactionFactory(txFactory)
       .dataSource(dataSource);
     configuration.setEnvironment(environmentBuilder.build());
    }
   }
  }
 }
private void mapperElement(XNode parent) throws Exception {
  if (parent != null) {
   for (XNode child : parent.getChildren()) {
    if ("package".equals(child.getName())) {
     String mapperPackage = child.getStringAttribute("name");
     configuration.addMappers(mapperPackage);
    } else {
     String resource = child.getStringAttribute("resource");
     String url = child.getStringAttribute("url");
     String mapperClass = child.getStringAttribute("class");
     if (resource != null && url == null && mapperClass == null) {
      ErrorContext.instance().resource(resource);
      InputStream inputStream = Resources.getResourceAsStream(resource);
      XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
      mapperParser.parse();
     } else if (resource == null && url != null && mapperClass == null) {
      ErrorContext.instance().resource(url);
      InputStream inputStream = Resources.getUrlAsStream(url);
      XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
      mapperParser.parse();
     } else if (resource == null && url == null && mapperClass != null) {
      Class<?> mapperInterface = Resources.classForName(mapperClass);
      configuration.addMapper(mapperInterface);
     } else {
      throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
     }
    }
   }
  }
 }

其中MapperRegistry對(duì)象中存放所有MapperProxyFactory對(duì)象的容器是一個(gè)hashmap

private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
 
public <T> void addMapper(Class<T> type) {
  if (type.isInterface()) {
   if (hasMapper(type)) {
    throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
   }
   boolean loadCompleted = false;
   try {
    knownMappers.put(type, new MapperProxyFactory<T>(type));
    // It's important that the type is added before the parser is run
    // otherwise the binding may automatically be attempted by the
    // mapper parser. If the type is already known, it won't try.
    MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
    parser.parse();
    loadCompleted = true;
   } finally {
    if (!loadCompleted) {
     knownMappers.remove(type);
    }
   }
  }
 }

在構(gòu)造factory的最后返回了一個(gè)DefaultSqlSessionFactory對(duì)象,并將創(chuàng)建好的Configuration對(duì)象當(dāng)作參數(shù)傳給了該對(duì)象,成為了他的成員變量。

第二步得到SqlSession對(duì)象

SqlSession session = sqlSessionFactory.openSession();

跟蹤獲取session的過(guò)程

 @Override
 public SqlSession openSession() {
  return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
 }
 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  Transaction tx = null;
  try {
   final Environment environment = configuration.getEnvironment();
   final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
   tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
   final Executor executor = configuration.newExecutor(tx, execType);
   return new DefaultSqlSession(configuration, executor, autoCommit);
  } catch (Exception e) {
   closeTransaction(tx); // may have fetched a connection so lets call close()
   throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
  } finally {
   ErrorContext.instance().reset();
  }
 }

最終得到的DefaultSqlSession中包含兩個(gè)重要對(duì)象,一個(gè)是從configuration里來(lái)的Enviroment,另外一個(gè)是包含TransactionFactroy對(duì)象的Executor對(duì)象。

其中獲得Executor對(duì)象的函數(shù)如下

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
  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);
  }
  executor = (Executor) interceptorChain.pluginAll(executor);
  return executor;
 }

這其中應(yīng)用的包裝模式(將SimpleExecutor對(duì)象包裝成CachingExecutor)和責(zé)任鏈模式(給CachingExecutro對(duì)象裝配上plugin)

第三步 根據(jù)傳入的接口信息生成動(dòng)態(tài)代理

TestMapper mapper=session.getMapper(TestMapper.class);

繼續(xù)跟蹤代碼

 @Override
 public <T> T getMapper(Class<T> type) {
  return configuration.<T>getMapper(type, this);
 }
 public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  return mapperRegistry.getMapper(type, sqlSession);
 }
@SuppressWarnings("unchecked")
 public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
  if (mapperProxyFactory == null) {
   throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
  }
  try {
   return mapperProxyFactory.newInstance(sqlSession);
  } catch (Exception e) {
   throw new BindingException("Error getting mapper instance. Cause: " + e, e);
  }
 }
 public T newInstance(SqlSession sqlSession) {
  final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
  return newInstance(mapperProxy);
 }
@SuppressWarnings("unchecked")
 protected T newInstance(MapperProxy<T> mapperProxy) {
  return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
 }

大致流程就是先從configuration中找mapperRegistry,再?gòu)膍apperRegistry中找當(dāng)初存放mapperfactory的hashmap,再?gòu)倪@個(gè)hashmap中找到相應(yīng)的mapperfactory,最后mapperfactory構(gòu)造了一個(gè)mapperproxy對(duì)象,并調(diào)用了java的Proxy類(lèi),構(gòu)造了一個(gè)動(dòng)態(tài)代理對(duì)象的實(shí)例。

看一下MapperProxy的代碼

/**
 *  Copyright 2009-2015 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.apache.ibatis.binding;
 
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
 
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.session.SqlSession;
 
/**
 * @author Clinton Begin
 * @author Eduardo Macarron
 */
public class MapperProxy<T> implements InvocationHandler, Serializable {
 
 private static final long serialVersionUID = -6424540398559729838L;
 private final SqlSession sqlSession;
 private final Class<T> mapperInterface;
 private final Map<Method, MapperMethod> methodCache;
 
 public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
  this.sqlSession = sqlSession;
  this.mapperInterface = mapperInterface;
  this.methodCache = methodCache;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  if (Object.class.equals(method.getDeclaringClass())) {
   try {
    return method.invoke(this, args);
   } catch (Throwable t) {
    throw ExceptionUtil.unwrapThrowable(t);
   }
  }
  final MapperMethod mapperMethod = cachedMapperMethod(method);
  return mapperMethod.execute(sqlSession, args);
 }
 
 private MapperMethod cachedMapperMethod(Method method) {
  MapperMethod mapperMethod = methodCache.get(method);
  if (mapperMethod == null) {
   mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
   methodCache.put(method, mapperMethod);
  }
  return mapperMethod;
 }
 
}

該class實(shí)現(xiàn)了InvocationHandler接口,我們知道java中的動(dòng)態(tài)代理模式需要代理class來(lái)實(shí)現(xiàn)InvocationHandler接口,

而最后動(dòng)態(tài)得到的實(shí)例調(diào)用函數(shù)實(shí)際上調(diào)用的是代理對(duì)象的invoke的函數(shù),所以我們第四步的入口就在這個(gè)class里

第四步 調(diào)用接口函數(shù)test,執(zhí)行sql語(yǔ)句

由代理對(duì)象中的inove函數(shù)知道,函數(shù)最后執(zhí)行的其實(shí)是MapperMethod類(lèi)的execute函數(shù)。

一路跟蹤代碼到SimpleExecutor下的doQuery函數(shù)中

 @Override
 public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
  Statement stmt = null;
  try {
   Configuration configuration = ms.getConfiguration();
   StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
   stmt = prepareStatement(handler, ms.getStatementLog());
   return handler.<E>query(stmt, resultHandler);
  } finally {
   closeStatement(stmt);
  }
 }

此處生成了一個(gè)StatementHandler對(duì)象和一個(gè)Statement對(duì)象

先看看Statement的生成過(guò)程

private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
  Statement stmt;
  Connection connection = getConnection(statementLog);
  stmt = handler.prepare(connection, transaction.getTimeout());
  handler.parameterize(stmt);
  return stmt;
 }

先生成Connection對(duì)象 ,用的也是代理模式

 protected Connection getConnection(Log statementLog) throws SQLException {
  Connection connection = transaction.getConnection();
  if (statementLog.isDebugEnabled()) {
   return ConnectionLogger.newInstance(connection, statementLog, queryStack);
  } else {
   return connection;
  }
 }
public static Connection newInstance(Connection conn, Log statementLog, int queryStack) {
  InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack);
  ClassLoader cl = Connection.class.getClassLoader();
  return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
 }

然后生成preparestatement

 @Override
 public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
  ErrorContext.instance().sql(boundSql.getSql());
  Statement statement = null;
  try {
   statement = instantiateStatement(connection);
   setStatementTimeout(statement, transactionTimeout);
   setFetchSize(statement);
   return statement;
  } catch (SQLException e) {
   closeStatement(statement);
   throw e;
  } catch (Exception e) {
   closeStatement(statement);
   throw new ExecutorException("Error preparing statement. Cause: " + e, e);
  }
 }
 @Override
 protected Statement instantiateStatement(Connection connection) throws SQLException {
  String sql = boundSql.getSql();
  if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
   String[] keyColumnNames = mappedStatement.getKeyColumns();
   if (keyColumnNames == null) {
    return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
   } else {
    return connection.prepareStatement(sql, keyColumnNames);
   }
  } else if (mappedStatement.getResultSetType() != null) {
   return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
  } else {
   return connection.prepareStatement(sql);
  }
 }

最后調(diào)用了connec tion的prepareStatement函數(shù),而因?yàn)閏onnection其實(shí)是一個(gè)代理對(duì)象,他實(shí)際調(diào)用的函數(shù)是

@Override
 public Object invoke(Object proxy, Method method, Object[] params)
   throws Throwable {
  try {
   if (Object.class.equals(method.getDeclaringClass())) {
    return method.invoke(this, params);
   }  
   if ("prepareStatement".equals(method.getName())) {
    if (isDebugEnabled()) {
     debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
    }    
    PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
    //實(shí)際調(diào)用創(chuàng)建prepareedstatement對(duì)象的地方
    stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
    return stmt;
   } else if ("prepareCall".equals(method.getName())) {
    if (isDebugEnabled()) {
     debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
    }    
    PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
    stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
    return stmt;
   } else if ("createStatement".equals(method.getName())) {
    Statement stmt = (Statement) method.invoke(connection, params);
    stmt = StatementLogger.newInstance(stmt, statementLog, queryStack);
    return stmt;
   } else {
    return method.invoke(connection, params);
   }
  } catch (Throwable t) {
   throw ExceptionUtil.unwrapThrowable(t);
  }
 }
public static PreparedStatement newInstance(PreparedStatement stmt, Log statementLog, int queryStack) {
  InvocationHandler handler = new PreparedStatementLogger(stmt, statementLog, queryStack);
  ClassLoader cl = PreparedStatement.class.getClassLoader();
  return (PreparedStatement) Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);
 }

發(fā)現(xiàn)原來(lái)這個(gè)pareparedStatement對(duì)象還是個(gè)代理對(duì)象

繼續(xù)跟蹤代碼

@Override
 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
  PreparedStatement ps = (PreparedStatement) statement;
  ps.execute();
  return resultSetHandler.<E> handleResultSets(ps);
 }

調(diào)用了之前生成的preparedStatement對(duì)象的execute函數(shù),其實(shí)也就是代理對(duì)象的inovke函數(shù)

@Override
 public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
  try {
   if (Object.class.equals(method.getDeclaringClass())) {
    return method.invoke(this, params);
   }     
   if (EXECUTE_METHODS.contains(method.getName())) {
    if (isDebugEnabled()) {
     debug("Parameters: " + getParameterValueString(), true);
    }
    clearColumnInfo();
    if ("executeQuery".equals(method.getName())) {
     ResultSet rs = (ResultSet) method.invoke(statement, params);
     return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
    } else {
     return method.invoke(statement, params);
    }
   } else if (SET_METHODS.contains(method.getName())) {
    if ("setNull".equals(method.getName())) {
     setColumn(params[0], null);
    } else {
     setColumn(params[0], params[1]);
    }
    return method.invoke(statement, params);
   } else if ("getResultSet".equals(method.getName())) {
    ResultSet rs = (ResultSet) method.invoke(statement, params);
    return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
   } else if ("getUpdateCount".equals(method.getName())) {
    int updateCount = (Integer) method.invoke(statement, params);
    if (updateCount != -1) {
     debug("  Updates: " + updateCount, false);
    }
    return updateCount;
   } else {
    return method.invoke(statement, params);
   }
  } catch (Throwable t) {
   throw ExceptionUtil.unwrapThrowable(t);
  }
 }

此時(shí)sql語(yǔ)句執(zhí)行完成,之后是獲取結(jié)果集

第五步 獲取結(jié)果集

@Override
 public List<Object> handleResultSets(Statement stmt) throws SQLException {
  ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
 
  final List<Object> multipleResults = new ArrayList<Object>();
 
  int resultSetCount = 0;
  ResultSetWrapper rsw = getFirstResultSet(stmt);
 
  List<ResultMap> resultMaps = mappedStatement.getResultMaps();
  int resultMapCount = resultMaps.size();
  validateResultMapsCount(rsw, resultMapCount);
  while (rsw != null && resultMapCount > resultSetCount) {
   ResultMap resultMap = resultMaps.get(resultSetCount);
   handleResultSet(rsw, resultMap, multipleResults, null);
   rsw = getNextResultSet(stmt);
   cleanUpAfterHandlingResultSet();
   resultSetCount++;
  }
 
  String[] resultSets = mappedStatement.getResultSets();
  if (resultSets != null) {
   while (rsw != null && resultSetCount < resultSets.length) {
    ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
    if (parentMapping != null) {
     String nestedResultMapId = parentMapping.getNestedResultMapId();
     ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
     handleResultSet(rsw, resultMap, null, parentMapping);
    }
    rsw = getNextResultSet(stmt);
    cleanUpAfterHandlingResultSet();
    resultSetCount++;
   }
  }
 
  return collapseSingleResultList(multipleResults);
 }

此處調(diào)用stmt.getResultSet(),然后他又進(jìn)了代理對(duì)象的invoke函數(shù)

@Override
 public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
  try {
   if (Object.class.equals(method.getDeclaringClass())) {
    return method.invoke(this, params);
   }     
   if (EXECUTE_METHODS.contains(method.getName())) {
    if (isDebugEnabled()) {
     debug("Parameters: " + getParameterValueString(), true);
    }
    clearColumnInfo();
    if ("executeQuery".equals(method.getName())) {
     ResultSet rs = (ResultSet) method.invoke(statement, params);
     return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
    } else {
     return method.invoke(statement, params);
    }
   } else if (SET_METHODS.contains(method.getName())) {
    if ("setNull".equals(method.getName())) {
     setColumn(params[0], null);
    } else {
     setColumn(params[0], params[1]);
    }
    return method.invoke(statement, params);
   } else if ("getResultSet".equals(method.getName())) {
    ResultSet rs = (ResultSet) method.invoke(statement, params);
    return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
   } else if ("getUpdateCount".equals(method.getName())) {
    int updateCount = (Integer) method.invoke(statement, params);
    if (updateCount != -1) {
     debug("  Updates: " + updateCount, false);
    }
    return updateCount;
   } else {
    return method.invoke(statement, params);
   }
  } catch (Throwable t) {
   throw ExceptionUtil.unwrapThrowable(t);
  }
 }
 public static ResultSet newInstance(ResultSet rs, Log statementLog, int queryStack) {
  InvocationHandler handler = new ResultSetLogger(rs, statementLog, queryStack);
  ClassLoader cl = ResultSet.class.getClassLoader();
  return (ResultSet) Proxy.newProxyInstance(cl, new Class[]{ResultSet.class}, handler);
 }

可以看到這還是一個(gè)代理模式,創(chuàng)建了一個(gè)用來(lái)獲取結(jié)果集的對(duì)象ResultSetLogger,看一下他的invoke函數(shù)

 @Override
 public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
  try {
   if (Object.class.equals(method.getDeclaringClass())) {
    return method.invoke(this, params);
   }  
   Object o = method.invoke(rs, params);
   if ("next".equals(method.getName())) {
    if (((Boolean) o)) {
     rows++;
     if (isTraceEnabled()) {
      ResultSetMetaData rsmd = rs.getMetaData();
      final int columnCount = rsmd.getColumnCount();
      if (first) {
       first = false;
       printColumnHeaders(rsmd, columnCount);
      }
      printColumnValues(columnCount);
     }
    } else {
     debug("   Total: " + rows, false);
    }
   }
   clearColumnInfo();
   return o;
  } catch (Throwable t) {
   throw ExceptionUtil.unwrapThrowable(t);
  }
 }

從ResultSetLogger對(duì)象遍歷出結(jié)果集還要經(jīng)過(guò)一步處理得到最終需要返回類(lèi)型的結(jié)果集

第六步 封裝結(jié)果集

private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
  try {
   if (parentMapping != null) {
    handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
   } else {
    if (resultHandler == null) {
     DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
     handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
     multipleResults.add(defaultResultHandler.getResultList());
    } else {
     handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
    }
   }
  } finally {
   // issue #228 (close resultsets)
   closeResultSet(rsw.getResultSet());
  }
 }
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
  if (resultMap.hasNestedResultMaps()) {
   ensureNoRowBounds();
   checkResultHandler();
   handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  } else {
   handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  }
 }
 private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
   throws SQLException {
  DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
  skipRows(rsw.getResultSet(), rowBounds);
  while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
   ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
   Object rowValue = getRowValue(rsw, discriminatedResultMap);
   storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
  }
 }
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
  final ResultLoaderMap lazyLoader = new ResultLoaderMap();
  Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
  if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
   final MetaObject metaObject = configuration.newMetaObject(resultObject);
   boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
   if (shouldApplyAutomaticMappings(resultMap, false)) {
    foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
   }
   foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
   foundValues = lazyLoader.size() > 0 || foundValues;
   resultObject = foundValues ? resultObject : null;
   return resultObject;
  }
  return resultObject;
 }

這一步最核心的代碼就是上面這個(gè)函數(shù),可以看到他是由configuration生成一個(gè)MetaObject,在通過(guò)applyAutomaticMappings函數(shù),將數(shù)據(jù)庫(kù)結(jié)果中相應(yīng)字段的值填充到MetaObject中,代碼如下

 private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
  List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
  boolean foundValues = false;
  if (autoMapping.size() > 0) {
   for (UnMappedColumnAutoMapping mapping : autoMapping) {
    final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
    if (value != null) {
     foundValues = true;
    }
    if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {
     // gcode issue #377, call setter on nulls (value is not 'found')
     metaObject.setValue(mapping.property, value);
    }
   }
  }
  return foundValues;
 }

最后將得到的封裝好的對(duì)象放入一個(gè)list中返回結(jié)果,關(guān)閉數(shù)據(jù)庫(kù)連接,一次完整的sql語(yǔ)句執(zhí)行流程至此完結(jié) 。

以上這篇mybatis3使用@Select等注解實(shí)現(xiàn)增刪改查操作就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 最新IntelliJ IDEA 2020版本的安裝教程詳解

    最新IntelliJ IDEA 2020版本的安裝教程詳解

    這篇文章主要介紹了最新IntelliJ IDEA 2020版本的安裝教程詳解,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Mybatis的xml文件時(shí)間范圍條件查詢方式

    Mybatis的xml文件時(shí)間范圍條件查詢方式

    這篇文章主要介紹了Mybatis的xml文件時(shí)間范圍條件查詢方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • springboot集成redis并使用redis生成全局唯一索引ID

    springboot集成redis并使用redis生成全局唯一索引ID

    本文主要介紹了springboot集成redis并使用redis生成全局唯一索引ID,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 如何在Spring Boot項(xiàng)目中使用Spring AI

    如何在Spring Boot項(xiàng)目中使用Spring AI

    Spring AI是Spring框架中用于集成和使用人工智能和機(jī)器學(xué)習(xí)功能的組件,它提供了一種簡(jiǎn)化的方式來(lái)與AI模型進(jìn)行交互,這篇文章主要介紹了Spring Boot 在項(xiàng)目中使用Spring AI,需要的朋友可以參考下
    2024-05-05
  • 因BigDecimal類(lèi)型數(shù)據(jù)引出的問(wèn)題詳析

    因BigDecimal類(lèi)型數(shù)據(jù)引出的問(wèn)題詳析

    Java在java.math包中提供的API類(lèi)BigDecimal,用來(lái)對(duì)超過(guò)16位有效位的數(shù)進(jìn)行精確的運(yùn)算,下面這篇文章主要給大家介紹了因BigDecimal類(lèi)型數(shù)據(jù)引出的問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-08-08
  • Java9 Stream Collectors新增功能(小結(jié))

    Java9 Stream Collectors新增功能(小結(jié))

    這篇文章主要介紹了Java9 Stream Collectors新增功能(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Springboot優(yōu)化內(nèi)置服務(wù)器Tomcat優(yōu)化方式(underTow)

    Springboot優(yōu)化內(nèi)置服務(wù)器Tomcat優(yōu)化方式(underTow)

    本文詳細(xì)介紹了Spring Boot中Tomcat和Undertow服務(wù)器的配置和優(yōu)化,包括初始線程數(shù)、最大線程數(shù)、最小備用線程數(shù)、最大請(qǐng)求數(shù)等參數(shù)的優(yōu)化建議,以及在高并發(fā)場(chǎng)景下Undertow相對(duì)于Tomcat的優(yōu)勢(shì)
    2024-12-12
  • Java中的Vector詳細(xì)解讀

    Java中的Vector詳細(xì)解讀

    這篇文章主要介紹了Java中的Vector詳細(xì)解讀,Vector是實(shí)現(xiàn)了List接口的子類(lèi),其底層是一個(gè)對(duì)象數(shù)組,維護(hù)了一個(gè)elementData數(shù)組,是線程安全的,Vector類(lèi)的方法帶有synchronized關(guān)鍵字,在開(kāi)發(fā)中考慮線程安全中使用Vector,需要的朋友可以參考下
    2023-09-09
  • Java基礎(chǔ)之多線程的三種實(shí)現(xiàn)方式

    Java基礎(chǔ)之多線程的三種實(shí)現(xiàn)方式

    這篇文章主要介紹了Java基礎(chǔ)之多線程的三種實(shí)現(xiàn)方式,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • java外賣(mài)訂餐系統(tǒng)小項(xiàng)目

    java外賣(mài)訂餐系統(tǒng)小項(xiàng)目

    這篇文章主要為大家詳細(xì)介紹了java外賣(mài)訂餐系統(tǒng)小項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01

最新評(píng)論

辉南县| 万荣县| 古田县| 怀宁县| 苗栗市| 宁陵县| 内江市| 桂阳县| 台东市| 宁晋县| 额敏县| 巫溪县| 怀宁县| 南宫市| 迁安市| 正定县| 万年县| 定远县| 福海县| 宜都市| 集贤县| 博野县| 虎林市| 广元市| 株洲市| 安吉县| 黄平县| 兴文县| 玉屏| 通海县| 巴塘县| 马边| 长丰县| 霍城县| 开鲁县| 伊吾县| 阳谷县| 女性| 怀安县| 红安县| 天镇县|