SqlMapper支持xml配置sql
This commit is contained in:
@@ -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 {
|
||||
|
||||
+1
@@ -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;
|
||||
|
||||
+4
-4
@@ -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>
|
||||
Reference in New Issue
Block a user