Mybatis Cursor

Cursor

  • 源码位置:org.apache.ibatis.cursor.Cursor
  • 继承Iterable说明是一个迭代器,继承Closeable说明有一个东西需要关闭
  1. public interface Cursor<T> extends Closeable, Iterable<T> {
  2. /**
  3. * 游标开始从数据库获取数据,返回true,反之false
  4. *
  5. * @return true if the cursor has started to fetch items from database.
  6. */
  7. boolean isOpen();
  8. /**
  9. * 数据库元素都被获取,返回true,反之false
  10. *
  11. * @return true if the cursor is fully consumed and has returned all elements matching the query.
  12. */
  13. boolean isConsumed();
  14. /**
  15. * 获取数据索引,从0开始,没有返回-1
  16. * Get the current item index. The first item has the index 0.
  17. *
  18. * @return -1 if the first cursor item has not been retrieved. The index of the current item retrieved.
  19. */
  20. int getCurrentIndex();
  21. }

DefaultCursor

  1. public class DefaultCursor<T> implements Cursor<T> {
  2. /**
  3. * 对象包装结果处理类
  4. */
  5. protected final ObjectWrapperResultHandler<T> objectWrapperResultHandler = new ObjectWrapperResultHandler<>();
  6. // ResultSetHandler stuff
  7. /**
  8. * ResultSet 处理器
  9. */
  10. private final DefaultResultSetHandler resultSetHandler;
  11. /**
  12. * 结果映射
  13. */
  14. private final ResultMap resultMap;
  15. /**
  16. * ResultSet 包装对象
  17. */
  18. private final ResultSetWrapper rsw;
  19. /**
  20. * 分页的
  21. */
  22. private final RowBounds rowBounds;
  23. /**
  24. * 游标的迭代器
  25. */
  26. private final CursorIterator cursorIterator = new CursorIterator();
  27. /**
  28. * 游标开启判断
  29. */
  30. private boolean iteratorRetrieved;
  31. /**
  32. * 游标状态,默认是创建未使用
  33. */
  34. private CursorStatus status = CursorStatus.CREATED;
  35. /**
  36. * 分页索引,默认-1
  37. */
  38. private int indexWithRowBound = -1;
  39. /**
  40. * 构造方法
  41. *
  42. * @param resultSetHandler
  43. * @param resultMap
  44. * @param rsw
  45. * @param rowBounds
  46. */
  47. public DefaultCursor(DefaultResultSetHandler resultSetHandler, ResultMap resultMap, ResultSetWrapper rsw, RowBounds rowBounds) {
  48. this.resultSetHandler = resultSetHandler;
  49. this.resultMap = resultMap;
  50. this.rsw = rsw;
  51. this.rowBounds = rowBounds;
  52. }
  53. @Override
  54. public boolean isOpen() {
  55. return status == CursorStatus.OPEN;
  56. }
  57. @Override
  58. public boolean isConsumed() {
  59. return status == CursorStatus.CONSUMED;
  60. }
  61. /**
  62. * 当前索引
  63. * @return
  64. */
  65. @Override
  66. public int getCurrentIndex() {
  67. return rowBounds.getOffset() + cursorIterator.iteratorIndex;
  68. }
  69. /**
  70. * 迭代器获取
  71. * @return
  72. */
  73. @Override
  74. public Iterator<T> iterator() {
  75. // 是否获取过
  76. if (iteratorRetrieved) {
  77. throw new IllegalStateException("Cannot open more than one iterator on a Cursor");
  78. }
  79. // 是否关闭
  80. if (isClosed()) {
  81. throw new IllegalStateException("A Cursor is already closed.");
  82. }
  83. iteratorRetrieved = true;
  84. return cursorIterator;
  85. }
  86. /**
  87. * {@link Closeable} 关闭{@link ResultSet}
  88. */
  89. @Override
  90. public void close() {
  91. // 判断是否关闭
  92. if (isClosed()) {
  93. return;
  94. }
  95. ResultSet rs = rsw.getResultSet();
  96. try {
  97. if (rs != null) {
  98. rs.close();
  99. }
  100. } catch (SQLException e) {
  101. // ignore
  102. } finally {
  103. // 设置游标状态
  104. status = CursorStatus.CLOSED;
  105. }
  106. }
  107. /**
  108. * 去到真正的数据行
  109. * @return
  110. */
  111. protected T fetchNextUsingRowBound() {
  112. T result = fetchNextObjectFromDatabase();
  113. while (objectWrapperResultHandler.fetched && indexWithRowBound < rowBounds.getOffset()) {
  114. result = fetchNextObjectFromDatabase();
  115. }
  116. return result;
  117. }
  118. /**
  119. * 从数据库获取数据
  120. * @return
  121. */
  122. protected T fetchNextObjectFromDatabase() {
  123. if (isClosed()) {
  124. return null;
  125. }
  126. try {
  127. objectWrapperResultHandler.fetched = false;
  128. // 游标状态设置
  129. status = CursorStatus.OPEN;
  130. if (!rsw.getResultSet().isClosed()) {
  131. // 处理数据结果放入,objectWrapperResultHandler
  132. resultSetHandler.handleRowValues(rsw, resultMap, objectWrapperResultHandler, RowBounds.DEFAULT, null);
  133. }
  134. } catch (SQLException e) {
  135. throw new RuntimeException(e);
  136. }
  137. // 获取处理结果
  138. T next = objectWrapperResultHandler.result;
  139. // 结果不为空
  140. if (objectWrapperResultHandler.fetched) {
  141. // 索引+1
  142. indexWithRowBound++;
  143. }
  144. // No more object or limit reached
  145. // 如果没有数据, 或者 当前读取条数= 偏移量+限额量
  146. if (!objectWrapperResultHandler.fetched || getReadItemsCount() == rowBounds.getOffset() + rowBounds.getLimit()) {
  147. // 关闭游标
  148. close();
  149. status = CursorStatus.CONSUMED;
  150. }
  151. // 设置结果为null
  152. objectWrapperResultHandler.result = null;
  153. return next;
  154. }
  155. /**
  156. * 是否关闭状态判断
  157. *
  158. * @return
  159. */
  160. private boolean isClosed() {
  161. return status == CursorStatus.CLOSED || status == CursorStatus.CONSUMED;
  162. }
  163. /**
  164. * 下一个索引
  165. * @return
  166. */
  167. private int getReadItemsCount() {
  168. return indexWithRowBound + 1;
  169. }
  170. /**
  171. * 游标的状态
  172. */
  173. private enum CursorStatus {
  174. /**
  175. * 新创建的游标, ResultSet 还没有使用过
  176. * A freshly created cursor, database ResultSet consuming has not started.
  177. */
  178. CREATED,
  179. /**
  180. * 游标使用过, ResultSet 被使用
  181. * A cursor currently in use, database ResultSet consuming has started.
  182. */
  183. OPEN,
  184. /**
  185. * 游标关闭, 可能没有被消费完全
  186. * A closed cursor, not fully consumed.
  187. */
  188. CLOSED,
  189. /**
  190. * 游标彻底消费完毕, 关闭了
  191. * A fully consumed cursor, a consumed cursor is always closed.
  192. */
  193. CONSUMED
  194. }
  195. /**
  196. * 对象处理结果的包装类
  197. * @param <T>
  198. */
  199. protected static class ObjectWrapperResultHandler<T> implements ResultHandler<T> {
  200. /**
  201. * 数据结果
  202. */
  203. protected T result;
  204. /**
  205. * 是否null
  206. */
  207. protected boolean fetched;
  208. /**
  209. * 从{@link ResultContext} 获取结果对象
  210. * @param context
  211. */
  212. @Override
  213. public void handleResult(ResultContext<? extends T> context) {
  214. this.result = context.getResultObject();
  215. context.stop();
  216. fetched = true;
  217. }
  218. }
  219. /**
  220. * 游标迭代器
  221. */
  222. protected class CursorIterator implements Iterator<T> {
  223. /**
  224. * 下一个数据
  225. * Holder for the next object to be returned.
  226. */
  227. T object;
  228. /**
  229. * 下一个的索引
  230. * Index of objects returned using next(), and as such, visible to users.
  231. */
  232. int iteratorIndex = -1;
  233. /**
  234. * 是否有下一个值
  235. * @return
  236. */
  237. @Override
  238. public boolean hasNext() {
  239. if (!objectWrapperResultHandler.fetched) {
  240. object = fetchNextUsingRowBound();
  241. }
  242. return objectWrapperResultHandler.fetched;
  243. }
  244. /**
  245. * 下一个值
  246. * @return
  247. */
  248. @Override
  249. public T next() {
  250. // Fill next with object fetched from hasNext()
  251. T next = object;
  252. if (!objectWrapperResultHandler.fetched) {
  253. next = fetchNextUsingRowBound();
  254. }
  255. if (objectWrapperResultHandler.fetched) {
  256. objectWrapperResultHandler.fetched = false;
  257. object = null;
  258. iteratorIndex++;
  259. return next;
  260. }
  261. throw new NoSuchElementException();
  262. }
  263. /**
  264. * 不可执行抛出异常
  265. */
  266. @Override
  267. public void remove() {
  268. throw new UnsupportedOperationException("Cannot remove element from Cursor");
  269. }
  270. }
  271. }