1. 自定义SqlSession
代码语言:javascript复制@Slf4j
public class GenericSqlSession extends DefaultSqlSession {
private static final ThreadLocal<Class<?>> CTX = new ThreadLocal<>();
private final Executor generalExecutor;
public GenericSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
super(configuration, executor, autoCommit);
this.generalExecutor = executor;
}
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
return doSelectList(statement, parameter, rowBounds);
}
protected <E> List<E> doSelectList(String statement, Object parameter, RowBounds rowBounds) {
try {
return generalExecutor.query(getCustomMappedStatement(statement),
ParamNameResolver.wrapToMapIfCollection(parameter, null), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}
protected MappedStatement getCustomMappedStatement(String statement) {
var ms = getConfiguration().getMappedStatement(statement);
var clazz = GenericSqlSession.get();
if (ObjectUtil.isEmpty(clazz)) {
return ms;
} else {
var resultMaps = ms.getResultMaps();
var resultMap = resultMaps.get(0);
var customMap = new ResultMap.Builder(getConfiguration(), resultMap.getId(),
clazz, resultMap.getResultMappings(), resultMap.getAutoMapping()).build();
return new MappedStatement.Builder(getConfiguration(), ms.getId(), ms.getSqlSource(), ms.getSqlCommandType())
.resultMaps(Collections.singletonList(customMap))
.resource(ms.getResource())
.useCache(ms.isUseCache())
.build();
}
}
public static void set(Class<?> clazz) {
CTX.set(clazz);
}
public static Class<?> get() {
return CTX.get();
}
public static void remove() {
CTX.remove();
}
}
2. 自定义SqlSessionFactory
代码语言:javascript复制public class GenericSqlSessionFactory extends DefaultSqlSessionFactory {
public GenericSqlSessionFactory(Configuration configuration) {
super(configuration);
}
@Override
public SqlSession openSession(ExecutorType execType) {
Transaction tx = null;
try {
final var environment = getConfiguration().getEnvironment();
final var transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), null, false);
final var executor = getConfiguration().newExecutor(tx, execType);
return new GenericSqlSession(getConfiguration(), executor, false);
} catch (Exception e) {
// may have fetched a connection so let's call close()
closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}
private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
if (environment == null || environment.getTransactionFactory() == null) {
return new ManagedTransactionFactory();
}
return environment.getTransactionFactory();
}
private void closeTransaction(Transaction tx) {
if (tx != null) {
try {
tx.close();
} catch (SQLException ignore) {
// Intentionally ignore. Prefer previous error.
}
}
}
}
3. 自定义SqlSessionTemplate
代码语言:javascript复制@Component
public class GenericSqlSessionTemplate extends SqlSessionTemplate {
public GenericSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
super(new GenericSqlSessionFactory(sqlSessionFactory.getConfiguration()));
}
}
4. 自定义基础Mapper
代码语言:javascript复制public interface SuperMapper<T> extends BaseMapper<T> {
/**
* selectById
*
* @param clazz 自定义结果集class
* @param id id
* @param <D> D
* @return D
*/
@SuppressWarnings("unchecked")
default <D> D selectById(Class<D> clazz, Serializable id) {
try {
GenericSqlSession.set(clazz);
return (D) selectById(id);
} finally {
GenericSqlSession.remove();
}
}
}
5. 使用
继承自定义的基础Mapper
代码语言:javascript复制@Data
@TableName("tag")
public class TagPO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
}
public interface TagDAO extends SuperMapper<TagPO> {
}
@Component
@Slf4j
public class MybatisTest implements CommandLineRunner {
@Autowired
TagDAO tagDAO;
@Override
public void run(String... args) throws Exception {
TagDTO id1 = tagDAO.selectById(TagDTO.class, 1);
log.info("{}", id1);
TagPO id2 = tagDAO.selectById(1);
log.info("{}", id2);
}
}