Skip to content

Commit

Permalink
BIGTOP-4219: Use annotation style config for MyBatis (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinw66 authored Sep 12, 2024
1 parent 83238f8 commit 1dc68a4
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@

package org.apache.bigtop.manager.dao.enums;

import lombok.Getter;

import java.util.stream.Stream;

@Getter
public enum DBType {
MYSQL("mysql", "MYSQL"),
DM("dm", "DaMeng");
Expand All @@ -33,18 +36,10 @@ public enum DBType {
private final String code;
private final String desc;

public String getCode() {
return this.code;
}

public String getDesc() {
return this.desc;
}

public static DBType toType(String databaseId) {
return Stream.of(DBType.values())
.filter(p -> p.getCode().equals(databaseId))
.findFirst()
.orElse(null);
.orElseThrow(() -> new IllegalArgumentException("Unsupported database: " + databaseId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@
* under the License.
*/

package org.apache.bigtop.manager.server.interceptor;
package org.apache.bigtop.manager.dao.interceptor;

import org.apache.bigtop.manager.common.utils.ClassUtils;
import org.apache.bigtop.manager.dao.annotations.CreateBy;
import org.apache.bigtop.manager.dao.annotations.CreateTime;
import org.apache.bigtop.manager.dao.annotations.UpdateBy;
import org.apache.bigtop.manager.dao.annotations.UpdateTime;
import org.apache.bigtop.manager.server.holder.SessionUserHolder;

import org.apache.commons.lang3.tuple.Pair;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
Expand All @@ -36,18 +34,16 @@
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;

import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

@Slf4j
@Component
@Intercepts({
@Signature(
type = Executor.class,
Expand All @@ -56,6 +52,12 @@
})
public class AuditingInterceptor implements Interceptor {

private final Supplier<Long> currentUser;

public AuditingInterceptor(Supplier<Long> currentUser) {
this.currentUser = currentUser;
}

@SuppressWarnings("unchecked")
@Override
public Object intercept(Invocation invocation) throws Throwable {
Expand Down Expand Up @@ -85,19 +87,9 @@ public Object intercept(Invocation invocation) throws Throwable {
return invocation.proceed();
}

private Pair<Long, Timestamp> getAuditInfo() {
// Get the current time and operator
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Long currentUser = SessionUserHolder.getUserId();
log.debug("timestamp: {} currentUser: {}", timestamp, currentUser);
return Pair.of(currentUser, timestamp);
}

private void setAuditFields(Object object, SqlCommandType sqlCommandType) throws IllegalAccessException {

Pair<Long, Timestamp> auditInfo = getAuditInfo();
Long currentUser = auditInfo.getLeft();
Timestamp timestamp = auditInfo.getRight();
Long userId = currentUser.get();
Timestamp timestamp = new Timestamp(System.currentTimeMillis());

List<Field> fields = ClassUtils.getFields(object.getClass());
if (SqlCommandType.INSERT == sqlCommandType || SqlCommandType.UPDATE == sqlCommandType) {
Expand All @@ -106,14 +98,14 @@ private void setAuditFields(Object object, SqlCommandType sqlCommandType) throws
field.setAccessible(true);
if (field.isAnnotationPresent(CreateBy.class)
&& SqlCommandType.INSERT == sqlCommandType
&& currentUser != null) {
field.set(object, currentUser);
&& userId != null) {
field.set(object, userId);
}
if (field.isAnnotationPresent(CreateTime.class) && SqlCommandType.INSERT == sqlCommandType) {
field.set(object, timestamp);
}
if (field.isAnnotationPresent(UpdateBy.class) && currentUser != null) {
field.set(object, currentUser);
if (field.isAnnotationPresent(UpdateBy.class) && userId != null) {
field.set(object, userId);
}
if (field.isAnnotationPresent(UpdateTime.class)) {
field.set(object, timestamp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@
*/
package org.apache.bigtop.manager.server;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableAsync
@EnableScheduling
@MapperScan("org.apache.bigtop.manager.dao")
@SpringBootApplication(scanBasePackages = {"org.apache.bigtop.manager.server", "org.apache.bigtop.manager.common"})
public class ServerApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* https://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.bigtop.manager.server.config;

import org.apache.bigtop.manager.dao.interceptor.AuditingInterceptor;
import org.apache.bigtop.manager.server.holder.SessionUserHolder;

import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.session.SqlSessionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

@Configuration
@MapperScan("org.apache.bigtop.manager.dao")
public class MyBatisConfig {

@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/*Mapper.xml"));

org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
configuration.setUseGeneratedKeys(true);
configuration.addInterceptor(new AuditingInterceptor(SessionUserHolder::getUserId));

sessionFactory.setDatabaseIdProvider(new ProductNameDatabaseIdProvider());
sessionFactory.setConfiguration(configuration);
return sessionFactory.getObject();
}

static class ProductNameDatabaseIdProvider implements DatabaseIdProvider {

@Override
public void setProperties(Properties p) {
// No properties to set
}

@Override
public String getDatabaseId(DataSource dataSource) throws SQLException {
try (Connection connection = dataSource.getConnection()) {
String databaseProductName = connection.getMetaData().getDatabaseProductName();
return switch (databaseProductName) {
case "MySQL" -> "mysql";
case "PostgreSQL" -> "postgresql";
default -> throw new IllegalArgumentException("Unsupported database: " + databaseProductName);
};
}
}
}
}

0 comments on commit 1dc68a4

Please sign in to comment.