package org.fanhongtao.mybatis.generator; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SpringLayout; import org.apache.commons.lang.WordUtils; import org.fanhongtao.log.LogUtils; import org.fanhongtao.xml.DigesterUtils; /** * @author Fan Hongtao * @created 2010-8-23 */ public class ServiceGenerator extends JFrame { private static final long serialVersionUID = 1L; private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); private JTextField outputDirText; private JTextField packageNameText; private JComboBox classNameCombo; private JTextField classDescText; private JTextArea mapperArea; private JTextArea xmlArea; private JTextArea serviceArea; private ExStringWriter mapperWriter; private ExStringWriter xmlWriter; private ExStringWriter serviceWriter; @SuppressWarnings("rawtypes") private Class clazz; private static Map<String, String> classMap = new LinkedHashMap<String, String>(); public ServiceGenerator() { ClassInfo classInfo = new ClassInfo(); InputStream input = classInfo.getClass().getResourceAsStream("classinfo.xml"); URL url = classInfo.getClass().getResource("classinfo_rules.xml"); try { classInfo = (ClassInfo)DigesterUtils.parse(classInfo, input, url); classMap = classInfo.getClassMap(); } catch (Exception e) { e.printStackTrace(); } setTitle("MyBatis Service Generator"); setLayout(new BorderLayout(10, 20)); JPanel inputPanel = new JPanel(); add(inputPanel, BorderLayout.NORTH); createInputPanel(inputPanel); JTabbedPane tabbedPane = new JTabbedPane(); add(tabbedPane, BorderLayout.CENTER); createTabbedPane(tabbedPane); packageNameText.setText(classInfo.getPgkName()); setSize(getPreferredSize()); // MyBatisConfig.setCfgFileName(""); } private void createInputPanel(final JPanel parent) { parent.setLayout(new BorderLayout()); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new GridLayout(2, 1, 3, 3)); parent.add(buttonPanel, BorderLayout.EAST); JPanel innerPanel = new JPanel(); innerPanel.setLayout(new BorderLayout()); parent.add(innerPanel, BorderLayout.CENTER); JPanel classPanel = new JPanel(); innerPanel.add(classPanel, BorderLayout.NORTH); JPanel dirPanel = new JPanel(); dirPanel.setLayout(new SpringLayout()); innerPanel.add(dirPanel, BorderLayout.CENTER); JLabel label = new JLabel("package: "); classPanel.add(label); packageNameText = new JTextField(30); // packageNameText.setText("org.fanhongtao.persistence"); classPanel.add(packageNameText); label = new JLabel("class: "); classPanel.add(label); classNameCombo = new JComboBox(); classPanel.add(classNameCombo); Iterator<Map.Entry<String, String>> iter = classMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<String, String> entry = iter.next(); classNameCombo.addItem(entry.getKey()); } classNameCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String desc = classMap.get(classNameCombo.getSelectedItem()); classDescText.setText(desc); } }); label = new JLabel("desc: "); classPanel.add(label); classDescText = new JTextField(10); classDescText.setText(classMap.get(classNameCombo.getSelectedItem())); classPanel.add(classDescText); label = new JLabel("Output Dir:"); dirPanel.add(label); outputDirText = new JTextField(60); outputDirText.setText("D:\\temp\\mybatis"); dirPanel.add(outputDirText); JButton btnChoose = new JButton("choose"); dirPanel.add(btnChoose); btnChoose.setMnemonic(java.awt.event.KeyEvent.VK_C); btnChoose.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFileChooser chooser = new JFileChooser(); chooser.setDialogTitle("Choose output dir"); chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int result = chooser.showOpenDialog(null); if (JFileChooser.APPROVE_OPTION == result) { outputDirText.setText(chooser.getSelectedFile().getPath()); } } }); JButton btnGenerate = new JButton("Generate"); buttonPanel.add(btnGenerate); btnGenerate.setMnemonic(java.awt.event.KeyEvent.VK_G); btnGenerate.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String className = packageNameText.getText() + "." + (String)classNameCombo.getSelectedItem(); try { generate(className, true); } catch (Exception e1) { e1.printStackTrace(); } } }); JButton btnGenerateAll = new JButton("Generate All"); buttonPanel.add(btnGenerateAll); btnGenerateAll.setMnemonic(java.awt.event.KeyEvent.VK_A); btnGenerateAll.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Iterator<Map.Entry<String, String>> iter = classMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<String, String> entry = iter.next(); classNameCombo.setSelectedItem(entry.getKey()); String className = packageNameText.getText() + "." + (String)classNameCombo.getSelectedItem(); try { generate(className, false); } catch (Exception e1) { e1.printStackTrace(); } } JOptionPane.showMessageDialog(parent, "Finished", "notice", JOptionPane.INFORMATION_MESSAGE); } }); } private void createTabbedPane(JTabbedPane tabbedPane) { mapperArea = new JTextArea(20, 90); mapperArea.setEditable(false); tabbedPane.addTab("Mapper", new JScrollPane(mapperArea)); xmlArea = new JTextArea(20, 90); xmlArea.setEditable(false); tabbedPane.addTab("XML", new JScrollPane(xmlArea)); serviceArea = new JTextArea(20, 90); serviceArea.setEditable(false); tabbedPane.addTab("Service", new JScrollPane(serviceArea)); } private void generate(String className, boolean showInScreen) throws Exception { clazz = Class.forName(className); Table table = new TableUtils(clazz).parseTable(); mapperWriter = new ExStringWriter(1024); xmlWriter = new ExStringWriter(1024); serviceWriter = new ExStringWriter(1024); generateHead(table); generateDeleteMethod(table); generateInsertMethod(table); generateQueryMethod(table); generateUpdateMethod(table); generateTail(table); if (showInScreen) { mapperArea.setText(mapperWriter.toString()); xmlArea.setText(xmlWriter.toString()); serviceArea.setText(serviceWriter.toString()); } String dir = outputDirText.getText(); writeFile(dir + "/iface", clazz.getSimpleName() + "Mapper.java", mapperWriter.toString()); writeFile(dir + "/mapper", clazz.getSimpleName() + "Mapper.xml", xmlWriter.toString()); writeFile(dir + "/service", clazz.getSimpleName() + "Service.java", serviceWriter.toString()); } private void writeFile(String dirName, String fileName, String content) throws IOException { File dir = new File(dirName); if (!dir.exists()) { try { dir.mkdirs(); } catch (Exception e) { JOptionPane.showMessageDialog(this, "Failed to create dir [" + dirName + "]", "Warning", JOptionPane.WARNING_MESSAGE); return; } } BufferedWriter writter = null; try { writter = new BufferedWriter(new FileWriter(dirName + "/" + fileName, false)); writter.write(content); } finally { if (null != writter) { writter.close(); } } } private void generateHead(Table table) { String pkgName = packageNameText.getText(); String mapperName = clazz.getSimpleName() + "Mapper"; String serviceName = clazz.getSimpleName() + "Service"; String mapperClass = pkgName + ".iface." + mapperName; String author = System.getenv("USERNAME"); String dateStr = formatter.format(new Date()); xmlWriter.writeln("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); xmlWriter.writeln("<!DOCTYPE mapper"); xmlWriter.writeln(" PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\""); xmlWriter.writeln(" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\"> "); xmlWriter.writeln(""); xmlWriter.writeln("<mapper namespace=\"" + mapperClass + "\">"); mapperWriter.writeln("package " + pkgName + ".iface"); mapperWriter.writeln(""); mapperWriter.writeln("import java.util.List;"); mapperWriter.writeln(""); mapperWriter.writeln("import org.apache.ibatis.session.RowBounds;"); mapperWriter.writeln(""); mapperWriter.writeln("import " + clazz.getName() + ";"); mapperWriter.writeln(""); mapperWriter.writeln("/**"); mapperWriter.writeln(" * @author " + author); mapperWriter.writeln(" * @created " + dateStr); mapperWriter.writeln(" */"); mapperWriter.writeln("public interface " + mapperName + " extends BasicMapper<" + clazz.getSimpleName() + ">"); serviceWriter.writeln("package " + pkgName + ".service"); serviceWriter.writeln(""); serviceWriter.writeln("import java.util.List;"); serviceWriter.writeln(""); serviceWriter.writeln("import org.apache.ibatis.session.RowBounds;"); serviceWriter.writeln("import org.apache.ibatis.session.SqlSession;"); serviceWriter.writeln("import " + mapperClass + ";"); serviceWriter.writeln("import " + clazz.getName() + ";"); serviceWriter.writeln(""); serviceWriter.writeln("/**"); serviceWriter.writeln(" * @author " + author); serviceWriter.writeln(" * @created " + dateStr); serviceWriter.writeln(" */"); serviceWriter.writeln("final class " + serviceName + " extends BaseService<" + clazz.getSimpleName() + ", " + mapperName + "> impements " + mapperName); serviceWriter.writeln("{"); serviceWriter.writeln(" public " + serviceName + "()"); serviceWriter.writeln(" {"); serviceWriter.writeln(" }"); serviceWriter.writeln(" "); serviceWriter.writeln(" public " + serviceName + "(SqlSession session)"); serviceWriter.writeln(" {"); serviceWriter.writeln(" super(session);"); serviceWriter.writeln(" }"); serviceWriter.writeln(" "); serviceWriter.writeln(" public " + mapperName + " getMapper()"); serviceWriter.writeln(" {"); serviceWriter.writeln(" return getSession().getMapper(" + mapperName + ".class);"); serviceWriter.writeln(" }"); serviceWriter.writeln(" "); } private void generateDeleteMethod(Table table) throws Exception { for (Index index : table.getIndexList()) { if (index.isUnique()) { generateDeleteMethod(table, index); } } } private void generateDeleteMethod(Table table, Index index) throws Exception, Exception { String type; String param; String methodName; List<String> columnList = index.getColumnList(); if (columnList.size() == 1) // 单字段的索引(或主键) { Field field = clazz.getDeclaredField(columnList.get(0)); type = field.getType().getSimpleName(); param = field.getName(); } else { type = clazz.getSimpleName(); param = WordUtils.uncapitalize(type); } methodName = "deleteBy"; for (int i = 0, n = columnList.size(); i < n; i++) { String column = columnList.get(i); if (i != 0) { methodName += "And"; } methodName += WordUtils.capitalize(column); } xmlWriter.writeln(" <delete id=\"" + methodName + "\" parameterType=\"" + type + "\">"); xmlWriter.write(" delete from " + table.getName() + " where "); for (int i = 0, n = columnList.size(); i < n; i++) { String column = columnList.get(i); if (i != 0) { xmlWriter.write(" and "); } xmlWriter.write(column + " = #{" + column + "}"); } xmlWriter.writeln(""); xmlWriter.writeln(" </delete>"); xmlWriter.writeln(" "); mapperWriter.writeln(" /**"); mapperWriter.writeln(" * @param " + param + " xxx"); mapperWriter.writeln(" * @return 删除的记录数"); mapperWriter.writeln(" */"); mapperWriter.writeln(" public int " + methodName + "(" + type + " " + param + ");"); mapperWriter.writeln(" "); serviceWriter.writeln(" /**"); serviceWriter.writeln(" * @param " + param + " xxx"); serviceWriter.writeln(" * @return 删除的记录数"); serviceWriter.writeln(" */"); serviceWriter.writeln(" public int " + methodName + "(" + type + " " + param + ")"); serviceWriter.writeln(" {"); serviceWriter.writeln(" return getMapper()." + methodName + "(" + param + ");"); serviceWriter.writeln(" }"); serviceWriter.writeln(" "); } /** * public int insert(Object obj); * @param table */ private void generateInsertMethod(Table table) { String type = clazz.getSimpleName(); String param = WordUtils.uncapitalize(type); String methodName = "insert"; StringBuilder sbColumn = new StringBuilder(1024); StringBuilder sbValue = new StringBuilder(1024); List<Column> columnList = table.getColumnList(); for (int i = 0, n = columnList.size(); i < n; i++) { if (i != 0) { sbColumn.append(", "); sbValue.append(", "); } Column column = columnList.get(i); sbColumn.append(column.getName()); sbValue.append("#{" + column.getName() + ",jdbcType=" + column.getType() + "}"); } xmlWriter.writeln(" <insert id=\"" + methodName + "\" parameterType=\"" + type + "\">"); xmlWriter.writeln(" insert into " + table.getName() + "(" + sbColumn.toString() + ") values (" + sbValue + ")"); xmlWriter.writeln(" </insert>"); xmlWriter.writeln(" "); mapperWriter.writeln(" /**"); mapperWriter.writeln(" * @param " + param + " xxx"); mapperWriter.writeln(" * @return 增加的记录数"); mapperWriter.writeln(" */"); mapperWriter.writeln(" public int " + methodName + "(" + type + " " + param + ");"); mapperWriter.writeln(" "); serviceWriter.writeln(" /**"); serviceWriter.writeln(" * @param " + param + " xxx"); serviceWriter.writeln(" * @return 增加的记录数"); serviceWriter.writeln(" */"); serviceWriter.writeln(" public int " + methodName + "(" + type + " " + param + ")"); serviceWriter.writeln(" {"); serviceWriter.writeln(" return getMapper()." + methodName + "(" + param + ")"); serviceWriter.writeln(" }"); serviceWriter.writeln(" "); } private void generateQueryMethod(Table table) throws Exception { for (Index index : table.getIndexList()) { if (index.isUnique()) { generateQueryMethod(table, index); } } } private void generateQueryMethod(Table table, Index index) throws Exception { String type; String param; String methodName; String resultType = clazz.getSimpleName(); String returnDesc; if (index.isUnique()) { returnDesc = "返回" + classDescText.getText() + "信息, null表示数据库中无对应的记录"; } else { returnDesc = "返回" + classDescText.getText() + "信息列表, List的Size为0表示数据库中无对应的记录"; } List<String> columnList = index.getColumnList(); if (columnList.size() == 1) // 单字段的索引(或主键) { Field field = clazz.getDeclaredField(columnList.get(0)); type = field.getType().getSimpleName(); param = field.getName(); } else { type = clazz.getSimpleName(); param = WordUtils.uncapitalize(type); } methodName = "queryBy"; for (int i = 0, n = columnList.size(); i < n; i++) { String column = columnList.get(i); if (i != 0) { methodName += "And"; } methodName += WordUtils.capitalize(column); } xmlWriter.writeln(" <select id=\"" + methodName + "\" parameterType=\"" + type + "\" resultType=\">" + resultType + "\""); xmlWriter.write(" select * from " + table.getName() + " where "); for (int i = 0, n = columnList.size(); i < n; i++) { String column = columnList.get(i); if (i != 0) { xmlWriter.write(" and "); } xmlWriter.write(column + " = #{" + column + "}"); } xmlWriter.writeln(""); xmlWriter.writeln(" </select>"); xmlWriter.writeln(" "); mapperWriter.writeln(" /**"); mapperWriter.writeln(" * @param " + param + " xxx"); mapperWriter.writeln(" * @return " + returnDesc); mapperWriter.writeln(" */"); mapperWriter.writeln(" public " + resultType + " " + methodName + "(" + type + " " + param + ");"); mapperWriter.writeln(" "); serviceWriter.writeln(" /**"); serviceWriter.writeln(" * @param " + param + " xxx"); serviceWriter.writeln(" * @return " + returnDesc); serviceWriter.writeln(" */"); serviceWriter.writeln(" public " + resultType + " " + methodName + "(" + type + " " + param + ")"); serviceWriter.writeln(" {"); serviceWriter.writeln(" return getMapper()." + methodName + "(" + param + ")"); serviceWriter.writeln(" }"); serviceWriter.writeln(" "); // 非唯一索引,还需要提供指定rowBounds的查询方法 if (!index.isUnique()) { mapperWriter.writeln(" /**"); mapperWriter.writeln(" * @param " + param + " xxx"); mapperWriter.writeln(" * @param rowBounds 所要查询的范围"); mapperWriter.writeln(" * @return " + returnDesc); mapperWriter.writeln(" */"); mapperWriter.writeln(" public " + resultType + " " + methodName + "(" + type + " " + param + ", RowBounds rowBounds);"); mapperWriter.writeln(" "); serviceWriter.writeln(" /**"); serviceWriter.writeln(" * @param " + param + " xxx"); serviceWriter.writeln(" * @param rowBounds 所要查询的范围"); serviceWriter.writeln(" * @return " + returnDesc); serviceWriter.writeln(" */"); serviceWriter.writeln(" public " + resultType + " " + methodName + "(" + type + " " + param + ", RowBounds rowBounds)"); serviceWriter.writeln(" {"); serviceWriter.writeln(" return getMapper()." + methodName + "(" + param + ", rowBounds)"); serviceWriter.writeln(" }"); serviceWriter.writeln(" "); } } private void generateUpdateMethod(Table table) throws Exception { for (Index index : table.getIndexList()) { if (index.isUnique()) { generateUpdateMethod(table, index); } } } private void generateUpdateMethod(Table table, Index index) throws Exception { String type; String param; String methodName; String returnDesc = "修改的记录数"; List<String> columnList = index.getColumnList(); if (columnList.size() == 1) // 单字段的索引(或主键) { Field field = clazz.getDeclaredField(columnList.get(0)); type = field.getType().getSimpleName(); param = field.getName(); } else { type = clazz.getSimpleName(); param = WordUtils.uncapitalize(type); } methodName = "updateBy"; for (int i = 0, n = columnList.size(); i < n; i++) { String column = columnList.get(i); if (i != 0) { methodName += "And"; } methodName += WordUtils.capitalize(column); } xmlWriter.writeln(" <delete id=\"" + methodName + "\" parameterType=\"" + type + "\""); xmlWriter.write(" delete from " + table.getName() + " where "); for (int i = 0, n = columnList.size(); i < n; i++) { String column = columnList.get(i); if (i != 0) { xmlWriter.write(" and "); } xmlWriter.write(column + " = #{" + column + "}"); } xmlWriter.writeln(""); xmlWriter.writeln(" </select>"); xmlWriter.writeln(" "); mapperWriter.writeln(" /**"); mapperWriter.writeln(" * @param " + param + " xxx"); mapperWriter.writeln(" * @return " + returnDesc); mapperWriter.writeln(" */"); mapperWriter.writeln(" public int " + methodName + "(" + type + " " + param + ");"); mapperWriter.writeln(" "); serviceWriter.writeln(" /**"); serviceWriter.writeln(" * @param " + param + " xxx"); serviceWriter.writeln(" * @return " + returnDesc); serviceWriter.writeln(" */"); serviceWriter.writeln(" public int " + methodName + "(" + type + " " + param + ")"); serviceWriter.writeln(" {"); serviceWriter.writeln(" return getMapper()." + methodName + "(" + param + ");"); serviceWriter.writeln(" }"); serviceWriter.writeln(" "); } private void generateTail(Table table) { xmlWriter.writeln("</mapper>"); mapperWriter.writeln("}"); serviceWriter.writeln("}"); } public static void main(String[] args) { LogUtils.initBasicLog(); ServiceGenerator frame = new ServiceGenerator(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }