You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MyBatis.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.db;
  21. import com.google.common.annotations.VisibleForTesting;
  22. import java.sql.PreparedStatement;
  23. import java.sql.ResultSet;
  24. import java.sql.SQLException;
  25. import java.util.Arrays;
  26. import java.util.Collections;
  27. import java.util.List;
  28. import javax.annotation.Nullable;
  29. import org.apache.ibatis.logging.LogFactory;
  30. import org.apache.ibatis.session.ExecutorType;
  31. import org.apache.ibatis.session.SqlSession;
  32. import org.apache.ibatis.session.SqlSessionFactory;
  33. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  34. import org.apache.ibatis.session.TransactionIsolationLevel;
  35. import org.sonar.api.Startable;
  36. import org.sonar.db.alm.pat.AlmPatMapper;
  37. import org.sonar.db.alm.setting.AlmSettingMapper;
  38. import org.sonar.db.alm.setting.ProjectAlmSettingMapper;
  39. import org.sonar.db.ce.CeActivityMapper;
  40. import org.sonar.db.ce.CeQueueMapper;
  41. import org.sonar.db.ce.CeScannerContextMapper;
  42. import org.sonar.db.ce.CeTaskCharacteristicDto;
  43. import org.sonar.db.ce.CeTaskCharacteristicMapper;
  44. import org.sonar.db.ce.CeTaskInputMapper;
  45. import org.sonar.db.ce.CeTaskMessageMapper;
  46. import org.sonar.db.component.AnalysisPropertiesMapper;
  47. import org.sonar.db.component.ApplicationProjectsMapper;
  48. import org.sonar.db.component.BranchMapper;
  49. import org.sonar.db.component.ComponentDto;
  50. import org.sonar.db.component.ComponentDtoWithSnapshotId;
  51. import org.sonar.db.component.ComponentKeyUpdaterMapper;
  52. import org.sonar.db.component.ComponentMapper;
  53. import org.sonar.db.component.ComponentWithModuleUuidDto;
  54. import org.sonar.db.component.FilePathWithHashDto;
  55. import org.sonar.db.component.KeyWithUuidDto;
  56. import org.sonar.db.component.ProjectLinkMapper;
  57. import org.sonar.db.component.ResourceDto;
  58. import org.sonar.db.component.ScrapAnalysisPropertyDto;
  59. import org.sonar.db.component.SnapshotDto;
  60. import org.sonar.db.component.SnapshotMapper;
  61. import org.sonar.db.component.UuidWithProjectUuidDto;
  62. import org.sonar.db.component.ViewsSnapshotDto;
  63. import org.sonar.db.duplication.DuplicationMapper;
  64. import org.sonar.db.duplication.DuplicationUnitDto;
  65. import org.sonar.db.es.EsQueueMapper;
  66. import org.sonar.db.event.EventComponentChangeMapper;
  67. import org.sonar.db.event.EventDto;
  68. import org.sonar.db.event.EventMapper;
  69. import org.sonar.db.issue.IssueChangeDto;
  70. import org.sonar.db.issue.IssueChangeMapper;
  71. import org.sonar.db.issue.IssueDto;
  72. import org.sonar.db.issue.IssueMapper;
  73. import org.sonar.db.issue.PrIssueDto;
  74. import org.sonar.db.mapping.ProjectMappingDto;
  75. import org.sonar.db.mapping.ProjectMappingsMapper;
  76. import org.sonar.db.measure.LiveMeasureMapper;
  77. import org.sonar.db.measure.MeasureDto;
  78. import org.sonar.db.measure.MeasureMapper;
  79. import org.sonar.db.measure.custom.CustomMeasureDto;
  80. import org.sonar.db.measure.custom.CustomMeasureMapper;
  81. import org.sonar.db.metric.MetricMapper;
  82. import org.sonar.db.newcodeperiod.NewCodePeriodMapper;
  83. import org.sonar.db.notification.NotificationQueueDto;
  84. import org.sonar.db.notification.NotificationQueueMapper;
  85. import org.sonar.db.permission.AuthorizationMapper;
  86. import org.sonar.db.permission.GroupPermissionDto;
  87. import org.sonar.db.permission.GroupPermissionMapper;
  88. import org.sonar.db.permission.UserPermissionDto;
  89. import org.sonar.db.permission.UserPermissionMapper;
  90. import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto;
  91. import org.sonar.db.permission.template.PermissionTemplateCharacteristicMapper;
  92. import org.sonar.db.permission.template.PermissionTemplateDto;
  93. import org.sonar.db.permission.template.PermissionTemplateGroupDto;
  94. import org.sonar.db.permission.template.PermissionTemplateMapper;
  95. import org.sonar.db.permission.template.PermissionTemplateUserDto;
  96. import org.sonar.db.plugin.PluginDto;
  97. import org.sonar.db.plugin.PluginMapper;
  98. import org.sonar.db.project.ProjectDto;
  99. import org.sonar.db.project.ProjectMapper;
  100. import org.sonar.db.property.InternalComponentPropertiesMapper;
  101. import org.sonar.db.property.InternalComponentPropertyDto;
  102. import org.sonar.db.property.InternalPropertiesMapper;
  103. import org.sonar.db.property.InternalPropertyDto;
  104. import org.sonar.db.property.PropertiesMapper;
  105. import org.sonar.db.property.ScrapPropertyDto;
  106. import org.sonar.db.purge.PurgeMapper;
  107. import org.sonar.db.purge.PurgeableAnalysisDto;
  108. import org.sonar.db.qualitygate.ProjectQgateAssociationDto;
  109. import org.sonar.db.qualitygate.ProjectQgateAssociationMapper;
  110. import org.sonar.db.qualitygate.QualityGateConditionDto;
  111. import org.sonar.db.qualitygate.QualityGateConditionMapper;
  112. import org.sonar.db.qualitygate.QualityGateDto;
  113. import org.sonar.db.qualitygate.QualityGateMapper;
  114. import org.sonar.db.qualityprofile.ActiveRuleDto;
  115. import org.sonar.db.qualityprofile.ActiveRuleMapper;
  116. import org.sonar.db.qualityprofile.ActiveRuleParamDto;
  117. import org.sonar.db.qualityprofile.DefaultQProfileMapper;
  118. import org.sonar.db.qualityprofile.QProfileChangeMapper;
  119. import org.sonar.db.qualityprofile.QProfileEditGroupsMapper;
  120. import org.sonar.db.qualityprofile.QProfileEditUsersMapper;
  121. import org.sonar.db.qualityprofile.QualityProfileExportMapper;
  122. import org.sonar.db.qualityprofile.QualityProfileMapper;
  123. import org.sonar.db.rule.RuleDto;
  124. import org.sonar.db.rule.RuleMapper;
  125. import org.sonar.db.rule.RuleParamDto;
  126. import org.sonar.db.rule.RuleRepositoryMapper;
  127. import org.sonar.db.schemamigration.SchemaMigrationDto;
  128. import org.sonar.db.schemamigration.SchemaMigrationMapper;
  129. import org.sonar.db.source.FileSourceMapper;
  130. import org.sonar.db.user.GroupDto;
  131. import org.sonar.db.user.GroupMapper;
  132. import org.sonar.db.user.GroupMembershipDto;
  133. import org.sonar.db.user.GroupMembershipMapper;
  134. import org.sonar.db.user.RoleMapper;
  135. import org.sonar.db.user.SamlMessageIdMapper;
  136. import org.sonar.db.user.SessionTokenMapper;
  137. import org.sonar.db.user.UserDismissedMessagesMapper;
  138. import org.sonar.db.user.UserDto;
  139. import org.sonar.db.user.UserGroupDto;
  140. import org.sonar.db.user.UserGroupMapper;
  141. import org.sonar.db.user.UserMapper;
  142. import org.sonar.db.user.UserPropertiesMapper;
  143. import org.sonar.db.user.UserTokenCount;
  144. import org.sonar.db.user.UserTokenDto;
  145. import org.sonar.db.user.UserTokenMapper;
  146. import org.sonar.db.webhook.WebhookDeliveryMapper;
  147. import org.sonar.db.webhook.WebhookMapper;
  148. public class MyBatis implements Startable {
  149. private final List<MyBatisConfExtension> confExtensions;
  150. private final Database database;
  151. private SqlSessionFactory sessionFactory;
  152. public MyBatis(Database database) {
  153. this(database, null);
  154. }
  155. public MyBatis(Database database, @Nullable MyBatisConfExtension[] confExtensions) {
  156. this.confExtensions = confExtensions == null ? Collections.emptyList() : Arrays.asList(confExtensions);
  157. this.database = database;
  158. }
  159. @Override
  160. public void start() {
  161. LogFactory.useSlf4jLogging();
  162. MyBatisConfBuilder confBuilder = new MyBatisConfBuilder(database);
  163. // DTO aliases, keep them sorted alphabetically
  164. confBuilder.loadAlias("ActiveRule", ActiveRuleDto.class);
  165. confBuilder.loadAlias("ActiveRuleParam", ActiveRuleParamDto.class);
  166. confBuilder.loadAlias("CeTaskCharacteristic", CeTaskCharacteristicDto.class);
  167. confBuilder.loadAlias("Component", ComponentDto.class);
  168. confBuilder.loadAlias("ComponentWithModuleUuid", ComponentWithModuleUuidDto.class);
  169. confBuilder.loadAlias("ComponentWithSnapshot", ComponentDtoWithSnapshotId.class);
  170. confBuilder.loadAlias("CustomMeasure", CustomMeasureDto.class);
  171. confBuilder.loadAlias("DuplicationUnit", DuplicationUnitDto.class);
  172. confBuilder.loadAlias("Event", EventDto.class);
  173. confBuilder.loadAlias("FilePathWithHash", FilePathWithHashDto.class);
  174. confBuilder.loadAlias("KeyWithUuid", KeyWithUuidDto.class);
  175. confBuilder.loadAlias("Group", GroupDto.class);
  176. confBuilder.loadAlias("GroupMembership", GroupMembershipDto.class);
  177. confBuilder.loadAlias("GroupPermission", GroupPermissionDto.class);
  178. confBuilder.loadAlias("InternalProperty", InternalPropertyDto.class);
  179. confBuilder.loadAlias("InternalComponentProperty", InternalComponentPropertyDto.class);
  180. confBuilder.loadAlias("IssueChange", IssueChangeDto.class);
  181. confBuilder.loadAlias("KeyLongValue", KeyLongValue.class);
  182. confBuilder.loadAlias("Issue", IssueDto.class);
  183. confBuilder.loadAlias("Measure", MeasureDto.class);
  184. confBuilder.loadAlias("NotificationQueue", NotificationQueueDto.class);
  185. confBuilder.loadAlias("PermissionTemplateCharacteristic", PermissionTemplateCharacteristicDto.class);
  186. confBuilder.loadAlias("PermissionTemplateGroup", PermissionTemplateGroupDto.class);
  187. confBuilder.loadAlias("PermissionTemplate", PermissionTemplateDto.class);
  188. confBuilder.loadAlias("PermissionTemplateUser", PermissionTemplateUserDto.class);
  189. confBuilder.loadAlias("Plugin", PluginDto.class);
  190. confBuilder.loadAlias("PrIssue", PrIssueDto.class);
  191. confBuilder.loadAlias("ProjectQgateAssociation", ProjectQgateAssociationDto.class);
  192. confBuilder.loadAlias("Project", ProjectDto.class);
  193. confBuilder.loadAlias("ProjectMapping", ProjectMappingDto.class);
  194. confBuilder.loadAlias("PurgeableAnalysis", PurgeableAnalysisDto.class);
  195. confBuilder.loadAlias("QualityGateCondition", QualityGateConditionDto.class);
  196. confBuilder.loadAlias("QualityGate", QualityGateDto.class);
  197. confBuilder.loadAlias("Resource", ResourceDto.class);
  198. confBuilder.loadAlias("RuleParam", RuleParamDto.class);
  199. confBuilder.loadAlias("Rule", RuleDto.class);
  200. confBuilder.loadAlias("SchemaMigration", SchemaMigrationDto.class);
  201. confBuilder.loadAlias("ScrapProperty", ScrapPropertyDto.class);
  202. confBuilder.loadAlias("ScrapAnalysisProperty", ScrapAnalysisPropertyDto.class);
  203. confBuilder.loadAlias("Snapshot", SnapshotDto.class);
  204. confBuilder.loadAlias("UserGroup", UserGroupDto.class);
  205. confBuilder.loadAlias("UserPermission", UserPermissionDto.class);
  206. confBuilder.loadAlias("UserTokenCount", UserTokenCount.class);
  207. confBuilder.loadAlias("UserToken", UserTokenDto.class);
  208. confBuilder.loadAlias("User", UserDto.class);
  209. confBuilder.loadAlias("UuidWithProjectUuid", UuidWithProjectUuidDto.class);
  210. confBuilder.loadAlias("ViewsSnapshot", ViewsSnapshotDto.class);
  211. confExtensions.forEach(ext -> ext.loadAliases(confBuilder::loadAlias));
  212. // keep them sorted alphabetically
  213. Class<?>[] mappers = {
  214. ActiveRuleMapper.class,
  215. AlmPatMapper.class,
  216. AlmSettingMapper.class,
  217. AnalysisPropertiesMapper.class,
  218. ApplicationProjectsMapper.class,
  219. AuthorizationMapper.class,
  220. BranchMapper.class,
  221. CeActivityMapper.class,
  222. CeQueueMapper.class,
  223. CeScannerContextMapper.class,
  224. CeTaskInputMapper.class,
  225. CeTaskCharacteristicMapper.class,
  226. CeTaskMessageMapper.class,
  227. ComponentKeyUpdaterMapper.class,
  228. ComponentMapper.class,
  229. LiveMeasureMapper.class,
  230. CustomMeasureMapper.class,
  231. DefaultQProfileMapper.class,
  232. DuplicationMapper.class,
  233. EsQueueMapper.class,
  234. EventMapper.class,
  235. EventComponentChangeMapper.class,
  236. FileSourceMapper.class,
  237. GroupMapper.class,
  238. GroupMembershipMapper.class,
  239. GroupPermissionMapper.class,
  240. InternalComponentPropertiesMapper.class,
  241. InternalPropertiesMapper.class,
  242. IsAliveMapper.class,
  243. IssueChangeMapper.class,
  244. IssueMapper.class,
  245. MeasureMapper.class,
  246. MetricMapper.class,
  247. NewCodePeriodMapper.class,
  248. NotificationQueueMapper.class,
  249. PermissionTemplateCharacteristicMapper.class,
  250. PermissionTemplateMapper.class,
  251. PluginMapper.class,
  252. ProjectAlmSettingMapper.class,
  253. ProjectLinkMapper.class,
  254. ProjectMapper.class,
  255. ProjectMappingsMapper.class,
  256. ProjectQgateAssociationMapper.class,
  257. PropertiesMapper.class,
  258. PurgeMapper.class,
  259. QProfileChangeMapper.class,
  260. QProfileEditGroupsMapper.class,
  261. QProfileEditUsersMapper.class,
  262. QualityGateConditionMapper.class,
  263. QualityGateMapper.class,
  264. QualityProfileMapper.class,
  265. QualityProfileExportMapper.class,
  266. RoleMapper.class,
  267. RuleMapper.class,
  268. RuleRepositoryMapper.class,
  269. SamlMessageIdMapper.class,
  270. SchemaMigrationMapper.class,
  271. SessionTokenMapper.class,
  272. SnapshotMapper.class,
  273. UserDismissedMessagesMapper.class,
  274. UserGroupMapper.class,
  275. UserMapper.class,
  276. UserPermissionMapper.class,
  277. UserPropertiesMapper.class,
  278. UserTokenMapper.class,
  279. WebhookMapper.class,
  280. WebhookDeliveryMapper.class
  281. };
  282. confBuilder.loadMappers(mappers);
  283. confExtensions.stream()
  284. .flatMap(MyBatisConfExtension::getMapperClasses)
  285. .forEach(confBuilder::loadMapper);
  286. sessionFactory = new SqlSessionFactoryBuilder().build(confBuilder.build());
  287. }
  288. @Override
  289. public void stop() {
  290. // nothing to do
  291. }
  292. @VisibleForTesting
  293. SqlSessionFactory getSessionFactory() {
  294. return sessionFactory;
  295. }
  296. public DbSession openSession(boolean batch) {
  297. if (batch) {
  298. SqlSession session = sessionFactory.openSession(ExecutorType.BATCH, TransactionIsolationLevel.READ_COMMITTED);
  299. return new BatchSession(session);
  300. }
  301. SqlSession session = sessionFactory.openSession(ExecutorType.REUSE, TransactionIsolationLevel.READ_COMMITTED);
  302. return new DbSessionImpl(session);
  303. }
  304. /**
  305. * Create a PreparedStatement for SELECT requests with scrolling of results
  306. */
  307. public PreparedStatement newScrollingSelectStatement(DbSession session, String sql) {
  308. int fetchSize = database.getDialect().getScrollDefaultFetchSize();
  309. return newScrollingSelectStatement(session, sql, fetchSize);
  310. }
  311. private static PreparedStatement newScrollingSelectStatement(DbSession session, String sql, int fetchSize) {
  312. try {
  313. PreparedStatement stmt = session.getConnection().prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
  314. stmt.setFetchSize(fetchSize);
  315. return stmt;
  316. } catch (SQLException e) {
  317. throw new IllegalStateException("Fail to create SQL statement: " + sql, e);
  318. }
  319. }
  320. }