Search in sources :

Example 1 with MyBatisProException

use of com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException in project mybatis-pro by Dreamroute.

the class MyBatisProUtil method processSpecialMethods.

public static Set<Resource> processSpecialMethods(Set<Resource> resources) {
    return resources.stream().map(resource -> {
        Class<?> mapperCls = getNamespaceFromXmlResource(resource);
        validateDuplicateMethods(mapperCls, resource);
        Document doc = createDocumentFromResource(resource);
        List<String> specialMethods = getSpecialMethods(mapperCls);
        if (!isEmpty(specialMethods)) {
            Class<?> entityCls = getTypeArgument(mapperCls);
            if (!hasAnnotation(entityCls, Table.class)) {
                throw new MyBatisProException("实体" + entityCls.getName() + "必须包含@" + Table.class.getName() + "注解");
            }
            // 将findBy方法的返回值的别名进行缓存,这里将缓存里面没有的返回值进行缓存,实体部分已经在前面进行了缓存,这里缓存非实体返回类型
            Map<String, String> name2Type = getMethodName2ReturnType(mapperCls);
            cacheAlias(name2Type);
            specialMethods.forEach(specialMethodName -> {
                String conditions = null;
                String sql = null;
                MapperLabel mapperLabel = SELECT;
                if (specialMethodName.startsWith("findBy")) {
                    conditions = specialMethodName.substring(6);
                    sql = "select * from ";
                } else if (specialMethodName.startsWith("deleteBy")) {
                    conditions = specialMethodName.substring(8);
                    sql = "delete from ";
                    mapperLabel = DELETE;
                } else if (specialMethodName.startsWith("countBy")) {
                    conditions = specialMethodName.substring(7);
                    sql = "select count(*) c from ";
                } else if (specialMethodName.startsWith("existBy")) {
                    conditions = specialMethodName.substring(7);
                    sql = "select (case when count(*)=0 then 'false' ELSE 'true' end) from ";
                }
                sql += getAnnotationValue(entityCls, Table.class) + " <where> " + createCondition(conditions, FIELDS_ALIAS_CACHE.get(entityCls));
                // 对于delete需要特殊处理,delete不需要设置resultType
                String resultType = mapperLabel == DELETE ? null : name2Type.get(specialMethodName);
                fillSqlNode(doc, mapperLabel, specialMethodName, resultType, sql, null, null);
            });
        }
        return createResourceFromDocument(doc);
    }).collect(toSet());
}
Also used : ID(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.ID) Arrays(java.util.Arrays) DocumentUtil.fillSqlNode(com.github.dreamroute.mybatis.pro.core.util.DocumentUtil.fillSqlNode) Table(com.github.dreamroute.mybatis.pro.core.annotations.Table) AnnotationUtil.hasAnnotation(cn.hutool.core.annotation.AnnotationUtil.hasAnnotation) ByteArrayResource(org.springframework.core.io.ByteArrayResource) Sets.difference(com.google.common.collect.Sets.difference) Collectors.toMap(java.util.stream.Collectors.toMap) Document(org.w3c.dom.Document) MAPPER(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.MAPPER) Arrays.asList(java.util.Arrays.asList) Map(java.util.Map) AnnotationUtil.getAnnotationValue(cn.hutool.core.annotation.AnnotationUtil.getAnnotationValue) DELETE(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.DELETE) Collectors.toSet(java.util.stream.Collectors.toSet) Resource(org.springframework.core.io.Resource) Set(java.util.Set) ClassUtil.loadClass(cn.hutool.core.util.ClassUtil.loadClass) Sets(com.google.common.collect.Sets) SqlUtil.toLine(com.github.dreamroute.mybatis.pro.core.util.SqlUtil.toLine) List(java.util.List) XPathParser(org.apache.ibatis.parsing.XPathParser) ClassUtil.getBaseMethodNames(com.github.dreamroute.mybatis.pro.core.util.ClassUtil.getBaseMethodNames) SELECT(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.SELECT) XNode(org.apache.ibatis.parsing.XNode) NAMESPACE(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.NAMESPACE) XMLMapperEntityResolver(org.apache.ibatis.builder.xml.XMLMapperEntityResolver) Arrays.stream(java.util.Arrays.stream) CollectionUtils.isEmpty(org.springframework.util.CollectionUtils.isEmpty) ClassUtil.getTypeArgument(cn.hutool.core.util.ClassUtil.getTypeArgument) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) DocumentUtil.createResourceFromDocument(com.github.dreamroute.mybatis.pro.core.util.DocumentUtil.createResourceFromDocument) Mapper(com.github.dreamroute.mybatis.pro.sdk.Mapper) DocumentUtil.createDocumentFromResource(com.github.dreamroute.mybatis.pro.core.util.DocumentUtil.createDocumentFromResource) JsonUtil.toJsonStr(com.github.dreamroute.mybatis.pro.base.enums.JsonUtil.toJsonStr) ClassUtil.getSpecialMethods(com.github.dreamroute.mybatis.pro.core.util.ClassUtil.getSpecialMethods) UTF_8(java.nio.charset.StandardCharsets.UTF_8) Optional.ofNullable(java.util.Optional.ofNullable) SetView(com.google.common.collect.Sets.SetView) Field(java.lang.reflect.Field) MapperLabel(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel) ClassUtil.getMethodName2ReturnType(com.github.dreamroute.mybatis.pro.core.util.ClassUtil.getMethodName2ReturnType) ClassUtil.scanPackageBySuper(cn.hutool.core.util.ClassUtil.scanPackageBySuper) Column(com.github.dreamroute.mybatis.pro.core.annotations.Column) ClassPathUtil(com.github.dreamroute.mybatis.pro.base.util.ClassPathUtil) StringUtils(org.springframework.util.StringUtils) ClassUtil.loadClass(cn.hutool.core.util.ClassUtil.loadClass) Arrays.asList(java.util.Arrays.asList) List(java.util.List) ArrayList(java.util.ArrayList) Document(org.w3c.dom.Document) DocumentUtil.createResourceFromDocument(com.github.dreamroute.mybatis.pro.core.util.DocumentUtil.createResourceFromDocument) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException) Collectors.toMap(java.util.stream.Collectors.toMap) Map(java.util.Map) HashMap(java.util.HashMap) MapperLabel(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel)

Example 2 with MyBatisProException

use of com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException in project mybatis-pro by Dreamroute.

the class MyBatisProUtil method getNamespaceFromXmlResource.

/**
 * 从mapper.xml文件中获取namespace
 *
 * @param resource mapper.xml数据流
 */
public static Class<?> getNamespaceFromXmlResource(Resource resource) {
    try {
        XPathParser xPathParser = new XPathParser(resource.getInputStream(), true, null, new XMLMapperEntityResolver());
        XNode mapperNode = xPathParser.evalNode(MAPPER.getCode());
        String namespace = mapperNode.getStringAttribute(NAMESPACE.getCode());
        return loadClass(namespace);
    } catch (Exception e) {
        throw new MyBatisProException("解析mapper.xml文件获取namespace出错", e);
    }
}
Also used : XMLMapperEntityResolver(org.apache.ibatis.builder.xml.XMLMapperEntityResolver) XPathParser(org.apache.ibatis.parsing.XPathParser) XNode(org.apache.ibatis.parsing.XNode) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException)

Example 3 with MyBatisProException

use of com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException in project mybatis-pro by Dreamroute.

the class DocumentUtil method createDocumentFromResource.

/**
 * 将Resource转换成Document
 */
public static Document createDocumentFromResource(Resource resource) {
    try {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
        documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
        documentBuilderFactory.setValidating(false);
        documentBuilderFactory.setNamespaceAware(false);
        DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
        // 此处需要设置EntityResolver,以便从classpath寻找dtd文件进行解析,否则会从网路下载,很慢并且可能会connect timeout
        builder.setEntityResolver(new XMLMapperEntityResolver());
        return builder.parse(resource.getInputStream());
    } catch (Exception e) {
        throw new MyBatisProException("创建Document失败", e);
    }
}
Also used : XMLMapperEntityResolver(org.apache.ibatis.builder.xml.XMLMapperEntityResolver) DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) DocumentBuilder(javax.xml.parsers.DocumentBuilder) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException)

Example 4 with MyBatisProException

use of com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException in project mybatis-pro by Dreamroute.

the class MyBatisProUtil method validateDuplicateMethods.

/**
 * 校验Mapper接口内的xxxBy方法不能与xml文件的方法有同名
 */
private static void validateDuplicateMethods(Class<?> mapperCls, Resource resource) {
    XPathParser xPathParser;
    try {
        xPathParser = new XPathParser(resource.getInputStream(), true, null, new XMLMapperEntityResolver());
    } catch (Exception e) {
        throw new MyBatisProException("解析" + mapperCls.getName() + "对应的mapper.xml文件失败!");
    }
    List<XNode> selectMethods = xPathParser.evalNodes("mapper/select");
    List<XNode> insertMethods = xPathParser.evalNodes("mapper/insert");
    List<XNode> updateMethods = xPathParser.evalNodes("mapper/update");
    List<XNode> deleteMethods = xPathParser.evalNodes("mapper/delete");
    List<XNode> methods = new ArrayList<>();
    methods.addAll(selectMethods);
    methods.addAll(insertMethods);
    methods.addAll(updateMethods);
    methods.addAll(deleteMethods);
    Set<String> xmlMethodNames = methods.stream().map(node -> node.getStringAttribute(ID.getCode())).collect(toSet());
    // BaseMapper的方法 + xxxBy方法
    Set<String> innerMethodNames = getBaseMethodNames();
    List<String> specialMethods = getSpecialMethods(mapperCls);
    innerMethodNames.addAll(specialMethods);
    SetView<String> intersection = Sets.intersection(xmlMethodNames, innerMethodNames);
    if (!isEmpty(intersection)) {
        throw new MyBatisProException("不允许接口" + mapperCls.getName() + "的方法" + toJsonStr(innerMethodNames) + "与" + resource.getFilename() + "文件中的方法重名");
    }
}
Also used : ID(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.ID) Arrays(java.util.Arrays) DocumentUtil.fillSqlNode(com.github.dreamroute.mybatis.pro.core.util.DocumentUtil.fillSqlNode) Table(com.github.dreamroute.mybatis.pro.core.annotations.Table) AnnotationUtil.hasAnnotation(cn.hutool.core.annotation.AnnotationUtil.hasAnnotation) ByteArrayResource(org.springframework.core.io.ByteArrayResource) Sets.difference(com.google.common.collect.Sets.difference) Collectors.toMap(java.util.stream.Collectors.toMap) Document(org.w3c.dom.Document) MAPPER(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.MAPPER) Arrays.asList(java.util.Arrays.asList) Map(java.util.Map) AnnotationUtil.getAnnotationValue(cn.hutool.core.annotation.AnnotationUtil.getAnnotationValue) DELETE(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.DELETE) Collectors.toSet(java.util.stream.Collectors.toSet) Resource(org.springframework.core.io.Resource) Set(java.util.Set) ClassUtil.loadClass(cn.hutool.core.util.ClassUtil.loadClass) Sets(com.google.common.collect.Sets) SqlUtil.toLine(com.github.dreamroute.mybatis.pro.core.util.SqlUtil.toLine) List(java.util.List) XPathParser(org.apache.ibatis.parsing.XPathParser) ClassUtil.getBaseMethodNames(com.github.dreamroute.mybatis.pro.core.util.ClassUtil.getBaseMethodNames) SELECT(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.SELECT) XNode(org.apache.ibatis.parsing.XNode) NAMESPACE(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.NAMESPACE) XMLMapperEntityResolver(org.apache.ibatis.builder.xml.XMLMapperEntityResolver) Arrays.stream(java.util.Arrays.stream) CollectionUtils.isEmpty(org.springframework.util.CollectionUtils.isEmpty) ClassUtil.getTypeArgument(cn.hutool.core.util.ClassUtil.getTypeArgument) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) DocumentUtil.createResourceFromDocument(com.github.dreamroute.mybatis.pro.core.util.DocumentUtil.createResourceFromDocument) Mapper(com.github.dreamroute.mybatis.pro.sdk.Mapper) DocumentUtil.createDocumentFromResource(com.github.dreamroute.mybatis.pro.core.util.DocumentUtil.createDocumentFromResource) JsonUtil.toJsonStr(com.github.dreamroute.mybatis.pro.base.enums.JsonUtil.toJsonStr) ClassUtil.getSpecialMethods(com.github.dreamroute.mybatis.pro.core.util.ClassUtil.getSpecialMethods) UTF_8(java.nio.charset.StandardCharsets.UTF_8) Optional.ofNullable(java.util.Optional.ofNullable) SetView(com.google.common.collect.Sets.SetView) Field(java.lang.reflect.Field) MapperLabel(com.github.dreamroute.mybatis.pro.core.consts.MapperLabel) ClassUtil.getMethodName2ReturnType(com.github.dreamroute.mybatis.pro.core.util.ClassUtil.getMethodName2ReturnType) ClassUtil.scanPackageBySuper(cn.hutool.core.util.ClassUtil.scanPackageBySuper) Column(com.github.dreamroute.mybatis.pro.core.annotations.Column) ClassPathUtil(com.github.dreamroute.mybatis.pro.base.util.ClassPathUtil) StringUtils(org.springframework.util.StringUtils) XMLMapperEntityResolver(org.apache.ibatis.builder.xml.XMLMapperEntityResolver) XPathParser(org.apache.ibatis.parsing.XPathParser) XNode(org.apache.ibatis.parsing.XNode) ArrayList(java.util.ArrayList) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException)

Example 5 with MyBatisProException

use of com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException in project mybatis-pro by Dreamroute.

the class DocumentUtil method createResourceFromDocument.

/**
 * 将Document转换成Resource
 */
public static Resource createResourceFromDocument(Document document) {
    try {
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, document.getDoctype().getPublicId());
        transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, document.getDoctype().getSystemId());
        transformer.setOutputProperty("encoding", "UTF-8");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        transformer.transform(new DOMSource(document), new StreamResult(bos));
        String xml = bos.toString("UTF-8");
        // 必须要将尖括号进行替换,否则要报错
        String replace = xml.replace("&gt;", ">").replace("&lt;", "<");
        NamedNodeMap attributes = document.getElementsByTagName(MAPPER.getCode()).item(0).getAttributes();
        String namespace = attributes.item(0).getTextContent();
        // 而mybatis-pro插件生成的resource都是byteArrayResource,如果不带desc,那么所有的resource的toString就都相同,反之带上desc的toString方法就能区分
        return new ByteArrayResource(replace.getBytes(StandardCharsets.UTF_8), namespace);
    } catch (Exception e) {
        throw new MyBatisProException("Document转成Resource失败", e);
    }
}
Also used : DOMSource(javax.xml.transform.dom.DOMSource) Transformer(javax.xml.transform.Transformer) NamedNodeMap(org.w3c.dom.NamedNodeMap) StreamResult(javax.xml.transform.stream.StreamResult) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteArrayResource(org.springframework.core.io.ByteArrayResource) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException) MyBatisProException(com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException)

Aggregations

MyBatisProException (com.github.dreamroute.mybatis.pro.core.exception.MyBatisProException)6 ArrayList (java.util.ArrayList)3 XMLMapperEntityResolver (org.apache.ibatis.builder.xml.XMLMapperEntityResolver)3 AnnotationUtil.getAnnotationValue (cn.hutool.core.annotation.AnnotationUtil.getAnnotationValue)2 AnnotationUtil.hasAnnotation (cn.hutool.core.annotation.AnnotationUtil.hasAnnotation)2 ClassUtil.getTypeArgument (cn.hutool.core.util.ClassUtil.getTypeArgument)2 ClassUtil.loadClass (cn.hutool.core.util.ClassUtil.loadClass)2 ClassUtil.scanPackageBySuper (cn.hutool.core.util.ClassUtil.scanPackageBySuper)2 JsonUtil.toJsonStr (com.github.dreamroute.mybatis.pro.base.enums.JsonUtil.toJsonStr)2 ClassPathUtil (com.github.dreamroute.mybatis.pro.base.util.ClassPathUtil)2 Column (com.github.dreamroute.mybatis.pro.core.annotations.Column)2 Table (com.github.dreamroute.mybatis.pro.core.annotations.Table)2 MapperLabel (com.github.dreamroute.mybatis.pro.core.consts.MapperLabel)2 DELETE (com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.DELETE)2 ID (com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.ID)2 MAPPER (com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.MAPPER)2 NAMESPACE (com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.NAMESPACE)2 SELECT (com.github.dreamroute.mybatis.pro.core.consts.MapperLabel.SELECT)2 ClassUtil.getBaseMethodNames (com.github.dreamroute.mybatis.pro.core.util.ClassUtil.getBaseMethodNames)2 ClassUtil.getMethodName2ReturnType (com.github.dreamroute.mybatis.pro.core.util.ClassUtil.getMethodName2ReturnType)2