package com.primeton.dgs.kernel.core.dao.hibernate; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.Text; import org.jdom.input.SAXBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import com.primeton.dgs.kernel.core.ex.HibernateStatementException; import com.primeton.dgs.kernel.core.util.MetadataWebContext; public class HibernateStatementSessionFactoryBean implements Serializable { private static final long serialVersionUID = 1L; private static final String PREFIX = "META-INF/sqlxml/"; // 加载模块的SQL文件的路径前缀 private static final String ENDFIX = "*Sql.xml"; // 文件名的扩展后缀名 final DatabaseRecognizer databaseRecognizer; private HibernateStatementSessionFactoryBean parent; private static HibernateStatementSessionFactoryBean instance; private Map> statements; private boolean ready = false; private Resource[] statementLocations; private boolean merge = false; public HibernateStatementSessionFactoryBean(DatabaseRecognizer databaseRecognizer) { instance = this; this.databaseRecognizer = databaseRecognizer; this.statements = new HashMap(); } public void setStatementResources(String[] statementResources) { setStatementResources(); } public void setStatementLocations(File[] statementLocations) { setStatementResources(); } public void setStatementLocations(Resource[] statementLocations) { this.statementLocations = statementLocations; } public void setStatementResources(String statementResources) { setStatementResources(); } private void setStatementResources() { try { //TODO 不同数据库,要区别加载数据文件 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); statementLocations = resolver.getResources("classpath*:" .concat(PREFIX) .concat(databaseRecognizer.getDbType()).concat("/").concat(ENDFIX)); } catch (IOException e) { log.error("加载 Native QuerySQL 异常。", e); } } public Resource[] getStatementLocations() { return this.statementLocations; } public boolean isReady() { return this.ready; } public HibernateStatementSessionFactoryBean getParent() { return this.parent; } public void setParent(HibernateStatementSessionFactoryBean parent) { this.parent = parent; } public boolean isMerge() { return this.merge; } public void setMerge(boolean merge) { this.merge = merge; } public void init() throws IOException { this.ready = false; this.statements.clear(); for (int i = 0; i < this.statementLocations.length; i++) { try(final InputStream inputStream = this.statementLocations[i].getInputStream();) { config(inputStream); log.info("read xml sql template file: {}", statementLocations[i].getURI()); } catch (Exception e) { log.error("parse sql xml error.", e); } } if ((isMerge()) && (this.parent != null)) { doMerge(); } this.ready = true; } private void doMerge() { if (this.parent != null) for (Iterator it = this.statements.keySet().iterator(); it .hasNext();) { String key = (String) it.next(); if (this.parent.statements.containsKey(key)) { throw new HibernateStatementException("statement of id=\"" + key + "\" has bean defined!"); } this.parent.statements.put(key, (List) this.statements.get(key)); } } public void config(InputStream in) throws IOException { SAXBuilder sb = new SAXBuilder(); try { Document doc = sb.build(in); Element root = doc.getRootElement(); List statements = root.getChildren("statement"); for (int i = 0; i < statements.size(); i++) { Element stmt = (Element) statements.get(i); String id = stmt.getAttributeValue("id"); if ((id == null) || ("".equals(id.trim()))) { throw new HibernateStatementException( "statement''s \"id\" should not be empty!"); } if (this.statements.containsKey(id)) { throw new HibernateStatementException("statement of id=\"" + id + "\" has bean defined!"); } List fields = stmt.getContent(); this.statements.put(id, readFields(fields)); } } catch (JDOMException e) { throw new HibernateStatementException("statement file is error!", e); } catch (IOException e) { throw new HibernateStatementException("statement file not exist!", e); } finally { if (in != null) in.close(); } } private List readFields(List fields) { List result = new ArrayList(); for (int j = 0; j < fields.size(); j++) { if ((fields.get(j) instanceof Text)) { String text = ((Text) fields.get(j)).getTextTrim(); if (!"".equals(text)) { result.add(new HibernateStatementTextField(text)); } } else if ((fields.get(j) instanceof Element)) { Element field = (Element) fields.get(j); if ("dynamic-field".equals(field.getName())) { result.add(readDynamicField(field)); } else if ("compare-field".equals(field.getName())) { result.add(readCompareField(field)); } else { throw new HibernateStatementException("\"" + field.getName() + "\" is not supportable!"); } } } return result; } private HibernateStatementDynamicField readDynamicField(Element field) { String property = field.getAttributeValue("property"); String onEmpty = field.getAttributeValue("onEmpty"); if ((property == null) || ("".equals(property))) { throw new HibernateStatementException( "\"property\" of dynamic-field is required!"); } HibernateStatementDynamicField f = new HibernateStatementDynamicField( property, onEmpty); List children = readFields(field.getContent()); f.getChildren().addAll(children); return f; } private HibernateStatementCompareField readCompareField(Element field) { String compare = field.getAttributeValue("compare"); String compareProperty = field.getAttributeValue("compareProperty"); String compareValue = field.getAttributeValue("compareValue"); if ((compare == null) || ("".equals(compare))) { throw new HibernateStatementException( "Attribute \"compare\" of compare-field is required!"); } if ((compareProperty == null) || ("".equals(compareProperty))) { throw new HibernateStatementException( "Attribute \"compareProperty\" of compare-field is required!"); } if ((compareValue == null)) { throw new HibernateStatementException( "Attribute \"compareValue\" of compare-field is required!"); } if (!HibernateStatementCompareField.isAvailableCompare(compare)) { throw new HibernateStatementException( "Attribute \"compare\" of compare-field is unavailable, the available value is (" + HibernateStatementCompareField.AVAILABLE_COMPARE + ")!"); } HibernateStatementCompareField f = new HibernateStatementCompareField( compare, compareProperty, compareValue); List children = readFields(field.getContent()); f.getChildren().addAll(children); return f; } public void destroy() { this.statements.clear(); this.ready = false; } public void refresh() throws IOException { destroy(); init(); } public List getStatement(String id) { List statementFields = this.statements.get(id); if (statementFields == null) { if (this.parent == null) { log.error("statement [id=\"" + id+ "\"]: not existed"); /*throw new HibernateStatementException("statement [id=\"" + id + "\"]: not existed");*/ return null; } return this.parent.getStatement(id); } return (List) statementFields; } public String getText(String id) { return getText(id, null); } public String getText(String id, Object vo) { List fileds = getStatement(id); if(null == fileds){ return null; } StringBuffer sb = new StringBuffer(); AtomicInteger index = new AtomicInteger(1); try { for (int i = 0; i < fileds.size(); i++) { StringBuffer s = ((HibernateStatementField) fileds.get(i)).getText(vo, index); if ((s != null) && (s.length() > 0)) sb.append(s).append(" "); } } catch (NumberFormatException e) { throw new HibernateStatementException("statement [id=\"" + id + "\"]: cannot format number " + e.getMessage()); } catch (Exception e) { throw new HibernateStatementException("statement [id=\"" + id + "\"]: " + e.getMessage(), e); } return sb.toString(); } public static String getStatementText(String id) { return getStatementText(id, null); } public static String getStatementText(String id, Object vo) { return instance.getText(id, vo); } public Object[] getParam(String id, Object vo) { List fileds = Optional.ofNullable(getStatement(id)).orElse(new ArrayList<>(0)); List result = new ArrayList(); for (int i = 0; i < fileds.size(); i++) { List list = ((HibernateStatementField) fileds.get(i)).getParam(vo); if ((list != null) && (!list.isEmpty())) { result.addAll(list); } } return result.toArray(); } public Map getParamMap(String id, Object vo) { if (!this.statements.containsKey(id)) { throw new HibernateStatementException("statement [id=\"" + id + "\"]: not existed"); } Map result = new HashMap(); List fileds = getStatement(id); for (int i = 0; i < fileds.size(); i++) { Map map = ((HibernateStatementField) fileds.get(i)).getParamMap(vo); if ((map != null) && (!map.isEmpty())) { result.putAll(map); } } return result; } public static Object[] getStatementParam(String id, Object vo) { return instance.getParam(id, vo); } public static Map getStatementParamMap(String id, Object vo) { return instance.getParamMap(id, vo); } public static boolean isStateReady() { return instance.isReady(); } public static void main(String[] args) throws Exception { final DatabaseRecognizer databaseRecognizer = new DatabaseRecognizer(); databaseRecognizer.setDbType("mysql"); HibernateStatementSessionFactoryBean factoryBean = new HibernateStatementSessionFactoryBean(databaseRecognizer); factoryBean.setStatementResources(""); factoryBean.init(); final HashMap vo = new HashMap<>(); vo.put("code", "abc"); vo.put("parentId", "ttttt"); vo.put("num", "ss"); vo.put("num2", null); System.out.println(factoryBean.getText("onlyOneEndByCode", vo)); System.out.println(Arrays.asList(factoryBean.getParam("onlyOneEndByCode", vo))); } }