/** * This method creates the sqlSessionManager of myBatis. It integrates all the SQL mappers * * @return a {@link SqlSessionFactory} */ private SqlSessionManager createSqlSessionManager() { Environment environment = new Environment(DEFAULT, this.transactionFactory, taskanaEngineConfiguration.getDatasource()); Configuration configuration = new Configuration(environment); // add mappers configuration.addMapper(TaskMapper.class); configuration.addMapper(TaskMonitorMapper.class); configuration.addMapper(WorkbasketMapper.class); configuration.addMapper(DistributionTargetMapper.class); configuration.addMapper(ClassificationMapper.class); configuration.addMapper(WorkbasketAccessMapper.class); configuration.addMapper(ObjectReferenceMapper.class); configuration.addMapper(QueryMapper.class); configuration.addMapper(AttachmentMapper.class); configuration.getTypeHandlerRegistry().register(MapTypeHandler.class); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(configuration); SqlSessionManager sessionManager = SqlSessionManager.newInstance(sessionFactory); return sessionManager; }
public static final SqlSessionManager[] get(final String... types) { if (types.length > 0) { final List<SqlSessionManager> managers = Lists.newArrayList(); for (final String type : types) { final SqlSessionManager manager = globals.get(type); if (manager == null) { throw new IllegalArgumentException("无效的数据源名称: " + type); } managers.add(manager); } return managers.toArray(new SqlSessionManager[managers.size()]); } return null; }
/** * Creates a new mybatis module binding the Datasource and SqlSessionManager with a name. * The guice key for that binding is available through {@link #getDatasourceKey}. * @param metricRegistry optional metric registry to expose hikari pool metrics */ public MyBatisModule(Properties properties, @Nullable String datasourceBindingName, @Nullable MetricRegistry metricRegistry, @Nullable Object healthCheckRegistry) { bindDatasource = datasourceBindingName != null; if (bindDatasource) { datasourceKey = Key.get(DataSource.class, Names.named(datasourceBindingName)); sessionManagerKey = Key.get(SqlSessionManager.class, Names.named(datasourceBindingName)); } else { datasourceKey = Key.get(DataSource.class); sessionManagerKey = Key.get(SqlSessionManager.class); } this.properties = properties; this.metricRegistry = metricRegistry; this.healthCheckRegistry = healthCheckRegistry; }
@Override protected void initialize() { LogFactory.useSlf4jLogging(); // makes things like logo_url map to logoUrl mapUnderscoreToCamelCase(true); // change MyBatis environment ID or set the default one String myBatisEnvId = properties.getProperty(MYBATIS_ENV_ID, DEFAULT_MYBATIS_ENV_ID); environmentId(myBatisEnvId); LOG.debug("Configuring MyBatis environmentId {}", myBatisEnvId); // check if some MyBatis configuration are provided Properties myBatisConfig = PropertiesUtil.removeProperties(properties, MYBATIS_CFG_PREFIX); Names.bindProperties(binder(), myBatisConfig); bindTransactionFactoryType(JdbcTransactionFactory.class); bindMappers(); bindTypeHandlers(); bindManagers(); if (bindDatasource) { bind(datasourceKey).to(DataSource.class); bind(sessionManagerKey).to(SqlSessionManager.class); } }
@Override public void verify() { SqlSessionManager sqlSessionManager = getInjector().getInstance(SqlSessionManager.class); if (sqlSessionManager != null) { try (SqlSessionManager ssm = sqlSessionManager) { if (!ssm.isManagedSessionStarted()) { ssm.startManagedSession(ExecutorType.SIMPLE, (TransactionIsolationLevel) null); } Connection connection = ssm.getConnection(); if (connection != null) { try (Connection conn = connection) { DatabaseMetaData dmd = conn.getMetaData(); if (dmd != null) { if (!compareBeanToTable(dmd, getBeanClasses(getConfig()))) { throw new IllegalStateException("compareBeanToTable returns false."); } } ssm.rollback(true); } catch (SQLException e) { throw new RuntimeException(e); } } } } }
protected static SqlSessionManager getSessionFromStack() { Stack<SqlSessionManager> stack = getSessionStack(); if (stack.isEmpty()) { return null; } return stack.peek(); }
@Override public void configure(final Binder binder) { GlobalSqlSession.keys().forEach(jdbcName -> { final SqlSessionManager manager = GlobalSqlSession.get(jdbcName); final String named = JDBC_NAMED_PRIFIX + jdbcName; binder.bind(SqlSession.class).annotatedWith(named(named)).toInstance(manager); binder.bind(SqlSessionManager.class).annotatedWith(named(named)).toInstance(manager); }); }
private boolean isManagedSessionStarted(final SqlSessionManager[] sqlSessionManager) { for (final SqlSessionManager manager : sqlSessionManager) { if (!manager.isManagedSessionStarted()) { return false; } } return true; }
private void startManagedSession(final MultiTransactional transactional, final SqlSessionManager[] sqlSessionManager) { for (final SqlSessionManager manager : sqlSessionManager) { if (!manager.isManagedSessionStarted()) { manager.startManagedSession(transactional.executorType(), transactional.isolation().getTransactionIsolationLevel()); } } }
private void rollback(final boolean force, final SqlSessionManager[] sqlSessionManager) { for (final SqlSessionManager manager : sqlSessionManager) { try { manager.rollback(true); } catch (final Throwable e) { // ignore } } }
private void close(final SqlSessionManager[] sqlSessionManager) { for (final SqlSessionManager manager : sqlSessionManager) { try { manager.close(); } catch (final Throwable e) { // ignore } } }
/** * Inits the SqlSessionManagerRegistry. */ @PostConstruct public void init() { if (this.factories.isUnsatisfied()) { throw new MybatisCdiConfigurationException("There are no SqlSessionFactory producers properly configured."); } Map<SqlSessionFactory, SqlSessionManager> m = new HashMap<SqlSessionFactory, SqlSessionManager>(); for (SqlSessionFactory factory : this.factories) { SqlSessionManager manager = SqlSessionManager.newInstance(factory); m.put(factory, manager); } this.managers = Collections.unmodifiableMap(m); }
private boolean start(Transactional transactional) { boolean started = false; for (SqlSessionManager manager : this.registry.getManagers()) { if (!manager.isManagedSessionStarted()) { manager.startManagedSession(transactional.executorType(), transactional.isolation().getTransactionIsolationLevel()); started = true; } } return started; }
protected static void pushSessionToStack(SqlSessionManager session) { getSessionStack().push(session); }
protected static void popSessionFromStack() { Stack<SqlSessionManager> stack = getSessionStack(); if (!stack.isEmpty()) { stack.pop(); } }
public static void set(final String type, final SqlSessionManager global) { globals.put(type, global); }
public static final SqlSessionManager get(final String type) { return globals.get(type); }
public MapperProvider(Class<T> mapperType, SqlSessionManager sqlSessionManager) { this.mapperType = mapperType; this.sqlSessionManager = sqlSessionManager; }
/** * {@inheritDoc} */ public Object invoke(final MethodInvocation invocation) throws Throwable { final Method interceptedMethod = invocation.getMethod(); MultiTransactional transactional = interceptedMethod.getAnnotation(MultiTransactional.class); // The annotation may be present at the class level instead if (transactional == null) { transactional = interceptedMethod.getDeclaringClass().getAnnotation(MultiTransactional.class); } final SqlSessionManager[] sqlSessionManager = GlobalSqlSession.get(transactional.envId()); if (sqlSessionManager == null || sqlSessionManager.length == 0) { if (log.isDebugEnabled()) { log.debug(format("没有配置数据源名称,不开启事务,直接执行数据库操作")); } return invocation.proceed(); } final boolean isSessionInherited = isManagedSessionStarted(sqlSessionManager); if (!isSessionInherited) { startManagedSession(transactional, sqlSessionManager); } Object object = null; boolean needsRollback = transactional.rollbackOnly(); try { object = invocation.proceed(); } catch (final Throwable t) { needsRollback = true; throw convertThrowableIfNeeded(invocation, transactional, t); } finally { if (!isSessionInherited) { try { if (needsRollback) { rollback(true, sqlSessionManager); } else { commit(transactional.force(), sqlSessionManager); } } finally { close(sqlSessionManager); } } } return object; }
private void commit(final boolean force, final SqlSessionManager[] sqlSessionManager) { for (final SqlSessionManager manager : sqlSessionManager) { manager.commit(true); } }
/** * @return the guice key for the bound sql session manager using a named binding if provided in constructor */ public Key<SqlSessionManager> getSessionManagerKey() { return sessionManagerKey; }
public SqlSessionManager getManager(SqlSessionFactory factory) { return this.managers.get(factory); }
public Collection<SqlSessionManager> getManagers() { return this.managers.values(); }
private void commit(Transactional transactional) { for (SqlSessionManager manager : this.registry.getManagers()) { manager.commit(transactional.force()); } }
private void rollback(Transactional transactional) { for (SqlSessionManager manager : this.registry.getManagers()) { manager.rollback(transactional.force()); } }
private void close() { for (SqlSessionManager manager : this.registry.getManagers()) { manager.close(); } }
private SqlSessionManager findSqlSessionManager(CreationalContext creationalContext) { SqlSessionFactory factory = CDIUtils.findSqlSessionFactory(this.sqlSessionFactoryName, this.qualifiers, creationalContext); return CDIUtils.getRegistry(creationalContext).getManager(factory); }
@ApplicationScoped @Produces @Named("unmanaged") public SqlSession createNonCdiManagedSession() throws IOException { return SqlSessionManager.newInstance(createSessionManager(4)); }
/** * With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis. SqlSessionManager is * the MyBatis object that wraps database connections. The purpose of this stack is to keep track of nested calls. * Each external API call is wrapped into taskanaEngineImpl.openConnection(); ..... * taskanaEngineImpl.returnConnection(); calls. In order to avoid duplicate opening / closing of connections, we use * the sessionStack in the following way: Each time, an openConnection call is received, we push the current * sessionManager onto the stack. On the first call to openConnection, we call sessionManager.startManagedSession() * to open a database connection. On each call to returnConnection() we pop one instance of sessionManager from the * stack. When the stack becomes empty, we close the database connection by calling sessionManager.close() * * @return Stack of SqlSessionManager */ protected static Stack<SqlSessionManager> getSessionStack() { Stack<SqlSessionManager> stack = sessionStack.get(); if (stack == null) { stack = new Stack<SqlSessionManager>(); sessionStack.set(stack); } return stack; }
/** * * @param <T> * @param mapperType */ final <T> void bindMapper(final Class<T> mapperType, final SqlSessionManager sessionManager) { bind(mapperType).toProvider(guicify(new MapperProvider<T>(mapperType, sessionManager))).in(Scopes.SINGLETON); }
/** * Sets the SqlSessionManager instance. * * @param sqlSessionManager the SqlSessionManager instance. */ public void setSqlSessionManager(SqlSessionManager sqlSessionManager) { this.sqlSessionManager = sqlSessionManager; }