SqlMapper支持xml配置sql

This commit is contained in:
aoshiguchen
2022-08-03 23:05:32 +08:00
parent 1b42119085
commit b07416ef06
9 changed files with 127 additions and 9 deletions
+5
View File
@@ -48,5 +48,10 @@
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
</project>
@@ -21,6 +21,8 @@
*/
package fun.asgc.neutrino.core.base;
import fun.asgc.neutrino.core.constant.MetaDataConstant;
/**
* 全局配置
* @author: aoshiguchen
@@ -46,6 +48,10 @@ public class GlobalConfig {
* 自动生成代码保存路径
*/
private static volatile String generatorCodeSavePath = "./lib/";
/**
* mapper文件存放基础路径
*/
private static volatile String mapperXmlFileBasePath = MetaDataConstant.CLASSPATH_RESOURCE_IDENTIFIER.concat("/mapper");
public static boolean isPrintGeneratorCode() {
return isPrintGeneratorCode;
@@ -78,4 +84,8 @@ public class GlobalConfig {
public static void setGeneratorCodeSavePath(String generatorCodeSavePath) {
GlobalConfig.generatorCodeSavePath = generatorCodeSavePath;
}
public static String getMapperXmlFileBasePath() {
return mapperXmlFileBasePath;
}
}
@@ -339,7 +339,7 @@ public abstract class AbstractBeanFactory implements BeanFactory, BeanRegistry,
* @param name
* @return
*/
private BeanWrapper findBean(Class<?> type, String name) {
protected BeanWrapper findBean(Class<?> type, String name) {
Assert.notNull(type, "bean的类型不能为空!");
Assert.notNull(name, "bean的名称不能为空!");
return beanCache.get(new BeanIdentity(name, type));
@@ -32,6 +32,7 @@ import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
/**
@@ -57,6 +58,7 @@ public class BeanWrapper implements LifeCycle {
private BeanInstantiationMode instantiationMode;
private Method instantiationMethod;
private boolean isNonIntercept;
private Set<BeanIdentity> innerDeanIdentitySet = new HashSet<>();
public boolean hasInstance() {
return null != instance;
@@ -150,4 +152,8 @@ public class BeanWrapper implements LifeCycle {
() -> beanIdentity
);
}
public Set<BeanIdentity> getInnerDeanIdentitySet() {
return innerDeanIdentitySet;
}
}
@@ -211,12 +211,21 @@ public class SimpleBeanFactory extends AbstractBeanFactory {
} else if (BeanInstantiationMode.METHOD == bean.getInstantiationMode()) {
// 通过bean方法实例化
BeanWrapper factoryBean = bean.getFactoryBean();
factoryBean.getInnerDeanIdentitySet().add(bean.getIdentity());
if (!factoryBean.hasInstance()) {
newInstance(factoryBean);
}
// 工厂bean,实例化方法执行前,工厂bean需要完成注入。但此时如果存在循环引用,这个注入只能完成一部分。实例化完成后,继续注入
if (factoryBean.getStatus() == BeanStatus.INSTANCE) {
inject(factoryBean);
}
if (bean.getInstantiationMethod().getParameters().length == 0) {
bean.setInstance(bean.getInstantiationMethod().invoke(factoryBean.getInstance()));
// 实例化完成后继续注入
if (null != bean.getInstance()) {
bean.setStatus(BeanStatus.INSTANCE);
}
inject(factoryBean);
} else {
// 暂时只处理一个参数的情况
Autowired autowired = bean.getInstantiationMethod().getParameters()[0].getAnnotation(Autowired.class);
@@ -231,6 +240,11 @@ public class SimpleBeanFactory extends AbstractBeanFactory {
arg = getBeanByTypeAndName(beanType, beanName);
}
bean.setInstance(bean.getInstantiationMethod().invoke(factoryBean.getInstance(), arg));
// 实例化完成后继续注入
if (null != bean.getInstance()) {
bean.setStatus(BeanStatus.INSTANCE);
}
inject(factoryBean);
}
} else if (BeanInstantiationMode.FACTORY == bean.getInstantiationMode()) {
@@ -267,16 +281,35 @@ public class SimpleBeanFactory extends AbstractBeanFactory {
bean.setStatus(BeanStatus.INJECT);
return;
}
boolean flag = true;
for (Field field : fieldSet) {
Autowired autowired = field.getAnnotation(Autowired.class);
if (null == autowired) {
continue;
}
// 已完成注入,无需重复注入
field.setAccessible(true);
Object oldObj = field.get(bean.getInstance());
if (null != oldObj) {
continue;
}
String beanName = autowired.value();
if (StringUtil.isEmpty(beanName)) {
beanName = field.getName();
}
Class<?> parameterType = autowired.parameterTypes().length == 0 ? Object.class : autowired.parameterTypes()[0];
// 临时解决自引用导致堆栈溢出的问题
BeanIdentity innerBeanIdentity = new BeanIdentity(beanName, field.getType());
if (bean.getInnerDeanIdentitySet().contains(innerBeanIdentity)) {
BeanWrapper beanWrapper = findBean(field.getType(), beanName);
if (null == beanWrapper || !beanWrapper.hasInstance()) {
flag = false;
continue;
}
}
BeanMatchMode matchMode = autowired.matchMode();
Object obj = null;
if (matchMode == BeanMatchMode.ByType) {
@@ -302,9 +335,12 @@ public class SimpleBeanFactory extends AbstractBeanFactory {
if (null == obj) {
throw new BeanException(String.format("Bean[type:%s name:%s field:%s] 注入异常", bean.getType().getName(), bean.getName(), field.getName()));
}
ReflectUtil.setFieldValue(field, bean.getInstance(), obj);
}
bean.setStatus(BeanStatus.INJECT);
if (flag) {
bean.setStatus(BeanStatus.INJECT);
}
}
);
} catch (BeanException e){
@@ -21,16 +21,26 @@
*/
package fun.asgc.neutrino.core.db.mapper;
import fun.asgc.neutrino.core.base.GlobalConfig;
import fun.asgc.neutrino.core.cache.Cache;
import fun.asgc.neutrino.core.cache.MemoryCache;
import fun.asgc.neutrino.core.constant.MetaDataConstant;
import fun.asgc.neutrino.core.db.annotation.*;
import fun.asgc.neutrino.core.util.CollectionUtil;
import fun.asgc.neutrino.core.util.FileUtil;
import fun.asgc.neutrino.core.util.LockUtil;
import fun.asgc.neutrino.core.util.StringUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Optional;
/**
* sql解析器
@@ -79,6 +89,9 @@ public class SqlParser {
this.targetMethodSign = String.format("%s#%s", targetMethod.getDeclaringClass().getName(), targetMethod.getName());
this.initByAnnotation();
this.initByXml();
if (StringUtil.isEmpty(sql)) {
throw new RuntimeException(String.format("%s sql不能为空!", targetMethodSign));
}
}
/**
@@ -98,7 +111,7 @@ public class SqlParser {
Select select = targetMethod.getAnnotation(Select.class);
this.sql = select.value();
if (StringUtil.isEmpty(sql)) {
throw new RuntimeException(String.format("%s sql不能为空!", targetMethod));
throw new RuntimeException(String.format("%s sql不能为空!", targetMethodSign));
}
this.isReturnCollection = Collection.class.isAssignableFrom(targetMethod.getReturnType());
if (isReturnCollection && null == resultClass) {
@@ -135,10 +148,45 @@ public class SqlParser {
* 根据xml文件进行初始化
*/
private void initByXml() {
if (!StringUtil.isEmpty(this.sql)) {
// if (!StringUtil.isEmpty(this.sql)) {
// return;
// }
String xmlPath = String.format("%s/%s.xml", GlobalConfig.getMapperXmlFileBasePath(), this.targetMethod.getDeclaringClass().getSimpleName());
String xmlStr = FileUtil.readContentAsString(xmlPath);
if (StringUtil.isEmpty(xmlStr)) {
return;
}
// TODO
try {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new StringReader(xmlStr));
Element rootElement = document.getRootElement();
if (CollectionUtil.isEmpty(rootElement.elements())) {
return;
}
Optional<Element> optionalElement = rootElement.elements().stream().filter(e -> e.attributeValue("id").equals(targetMethod.getName())).findFirst();
if (!optionalElement.isPresent()) {
return;
}
Element element = optionalElement.get();
this.sql = element.getText().replaceAll("\n", "").replaceAll( " ", " ");
if (element.getName().equals("select")) {
this.operatorType = SqlOperatorType.SELECT;
} else if (element.getName().equals("update")) {
this.operatorType = SqlOperatorType.UPDATE;
} else if (element.getName().equals("delete")) {
this.operatorType = SqlOperatorType.DELETE;
} else if (element.getName().equals("insert")) {
this.operatorType = SqlOperatorType.INSERT;
}
if (!StringUtil.isEmpty(element.attributeValue("resultType"))) {
this.resultComponentType = Class.forName(element.attributeValue("resultType"));
}
if (StringUtil.isEmpty(sql)) {
throw new RuntimeException(String.format("%s sql不能为空!", targetMethodSign));
}
} catch (Exception e) {
throw new RuntimeException(String.format("Mapper文件[%s]异常! %s", xmlPath, e.getMessage()));
}
}
public static SqlParser getInstance(Method targetMethod) throws Exception {
@@ -22,6 +22,7 @@
package fun.asgc.neutrino.proxy.server.base.rest.config;
import fun.asgc.neutrino.core.annotation.Configuration;
import fun.asgc.neutrino.core.annotation.Init;
import fun.asgc.neutrino.core.annotation.NonIntercept;
import fun.asgc.neutrino.core.annotation.Value;
import lombok.Data;
@@ -28,8 +28,6 @@ import fun.asgc.neutrino.core.db.annotation.Select;
import fun.asgc.neutrino.core.db.mapper.SqlMapper;
import fun.asgc.neutrino.proxy.server.dal.entity.UserTokenDO;
import java.util.Date;
/**
*
* @author: aoshiguchen
@@ -39,19 +37,21 @@ import java.util.Date;
public interface UserTokenMapper extends SqlMapper {
/**
* 新增用户token
* 支持注解 + xml配置2种方式
* @param userToken
* @return
*/
@Insert("insert into `user_token`(`token`,`user_id`,`expiration_time`,`create_time`,`update_time`) values (:token,:userId,:expirationTime,:createTime,:updateTime)")
// @Insert("insert into `user_token`(`token`,`user_id`,`expiration_time`,`create_time`,`update_time`) values (:token,:userId,:expirationTime,:createTime,:updateTime)")
int add(UserTokenDO userToken);
/**
* 根据token查询单条记录
* 支持注解 + xml配置2种方式
* @param token
* @param time
* @return
*/
@Select("select * from user_token where token = ? and expiration_time > ?")
// @Select("select * from user_token where token = ? and expiration_time > ?")
UserTokenDO findByAvailableToken(String token, Long time);
/**
@@ -0,0 +1,12 @@
<mapper namespace = "fun.asgc.neutrino.proxy.server.dal.UserTokenMapper">
<insert id = "add">
insert into `user_token`(`token`,`user_id`,`expiration_time`,`create_time`,`update_time`)
values (:token, :userId, :expirationTime, :createTime, :updateTime)
</insert>
<select id = "findByAvailableToken">
select * from user_token where token = ? and expiration_time > ?
</select>
</mapper>