笔者一直比较反感程序员使用mybatis官方提供的mapper逆向生成工具(根据数据库表自动生成mapper接口、mapper.xml以及实体bean)。
因为笔者认为程序员使用mapper逆向生成工具(官方)会带来很多不好的影响,甚至让代码臃肿难以维护。 理由列举如下:
1、使用官方mapper逆向生成工具,程序员变得越来越懒,且容易养成依赖工具的恶习,离开了工具,很多底层的sql自己往往都不会写。
2、官方mapper逆向生成器 会产生大量的xml冗余代码充塞其中,不够优雅。笔者认为其生成sql的可靠性、可扩展性也不高,且难以维护。
3、相比自己手写sql,程序员自身的代码功底得不到提高,对业务的理解也不够透彻。无论是对个人还是团队而言,其影响都是极其恶劣的。
从开发效率上来将,官方mapper逆向生成工具似乎提高了程序员的生产力(因为程序员再也不用写基本的CRUD了),但是与其带来的一系列恶劣影响相比,这种提升简直微乎其微。
从笔者从事软件开发的这几年看,几乎所有的项目经理都一致认为,使用官方mapper逆向生成工具带来影响的恶劣程度,远远超出其带来的所谓开发效率的提升。周边程序员们也大多赞同使用手写或自己开发生成工具,虽然也有少数程序员喜欢官方mapper逆向生成工具的。笔者发现:开发年限越长的程序员,越是喜欢自己手写sql或自己开发生成工具,而那些喜欢官方mapper逆向生成工具的大多都是新手或低级程序员。
笔者当然是喜欢手写sql的(这更接近sql底层而且写起来更加舒畅自如,代码也更安全可靠),当然为了兼顾开发效率,笔者自己开发了一个mapper生成器(图形化工具),一个十分小巧的图形化生成工具,总共才3个类,不到800行代码。目前适用于mysql数据库表的逆向生成。全部源代码如下,希望大家喜欢。
项目git地址: https://github.com/jellyflu/mapperGen
GenDemo.java
package com.jelly.mapperGen;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;
public class GenDemo extends JFrame implements ActionListener{
private static final long serialVersionUID = 4284020376229953894L;
private JLabel label1,label2,label3;//labe1 文本标签 1 2 3
private JLabel label4;
private JTextField textField1 ,textField2;//文本输入框1 2
private JTextField textField3;
private JScrollPane scrollPanel1 ,scrollPanel2;//滚动面板1 滚动面板2
private JTextArea textArea1 ,textArea2;//文本域1 文本域2
private JButton button1 ,button2 ,button3;// 按钮3个 生成xml 清空 保存到文件
private JButton button4;//按钮4 生成bean代码
private JButton button5;// 清空textArea1 内容
private JButton button6;//生成mapper接口
private String savedir;//保存文件目录
public static void main(String[] args){
GenDemo demo =new GenDemo();
demo.init();
}
public void init(){
this.setTitle("GenMapper工具");
// this.setBounds(0, 0, 600, 550);
this.setBounds(0, 0, 700, 600);
this.setLayout(null);
label1=new JLabel("表名:");
label2=new JLabel("实体名(简单):");
label3=new JLabel("表字段(列)声明");
label4=new JLabel("mapper命名空间:");
label1.setBounds(20, 20, 80, 20);
label2.setBounds(20, 50, 80, 20); label4.setBounds(205, 50, 100, 20);
label3.setBounds(20, 80, 100, 20);
button5=new JButton("清空");
button5.setBounds(130, 80, 80, 25);
this.add(label1);
this.add(label2);
this.add(label3);
this.add(label4);
this.add(button5);
textField1=new JTextField();
textField2=new JTextField();
textField3=new JTextField();
textField1.setBounds(100, 20, 100, 20);
textField2.setBounds(100, 50, 100, 20);
textField3.setBounds(310, 50, 230, 20);
this.add(textField1);
this.add(textField2);
this.add(textField3);
textArea1=new JTextArea();
textArea2=new JTextArea();
scrollPanel1=new JScrollPane(textArea1);
scrollPanel1.setBounds(20, 110, 640, 150);
scrollPanel2=new JScrollPane(textArea2);
scrollPanel2.setBounds(20, 310, 640, 210);
button1=new JButton("生成xml");
button2=new JButton("清空");
button3=new JButton("保存到文件");
button4=new JButton("生成bean");
button6=new JButton("生成接口");
button1.setBounds(20, 270, 100, 25);
button2.setBounds(130, 270, 80, 25);
button3.setBounds(220, 270, 100, 25);
button4.setBounds(330, 270, 100, 25);
button6.setBounds(440, 270, 100, 25);
this.add(button1);
this.add(button2);
this.add(button3);
this.add(button4);
this.add(button6);
this.add(scrollPanel1);
this.add(scrollPanel2);
//this.setResizable(false);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFUtils.positionCenter(this);
initEvent();//初始化事件 注册事件处理程序
}
public void initEvent(){
button1.addActionListener(this);
button1.setActionCommand("generateXML");
button2.addActionListener(this);
button2.setActionCommand("clearXML");
button3.addActionListener(this);
button3.setActionCommand("saveFile");
button4.setActionCommand("generateBean");
button4.addActionListener(this);
button5.setActionCommand("clearDeclare");
button5.addActionListener(this);
button6.setActionCommand("generateInter");
button6.addActionListener(this);
textArea2.addKeyListener(new KeyListener() {//键盘监听事件
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.isControlDown()&& e.getKeyCode() == KeyEvent.VK_S) {
//System.out.println("ctrl +S has pressed");
saveFile();//保存
}
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
String command= e.getActionCommand();
switch(command){
case "generateXML":
generateXML();
break;
case "clearXML":
clearXML();
break;
case "saveFile":
saveFile();
break;
case "generateBean":
generateBean();
break;
case "clearDeclare":
clearDeclare();
break;
case "generateInter":
generateInter();
break;
}
}
public String firstLetterLowercase(String str){
String s= str.substring(1);
char letter=Character.toLowerCase(str.charAt(0));
return letter+s;
}
//生成mapper 接口
private void generateInter() {
String entityName=this.textField2.getText();//实体名(简单名称) Book
String fieldsDeclare=this.textArea1.getText();
String fieldTypeRegex="(?<=`)\\s+[\\w\\(\\)]+";
if(fieldsDeclare==null||fieldsDeclare.trim().equals("")){
JOptionPane.showMessageDialog(this, "表字段(列)声明不能为空!"); return ;
}
if(entityName==null||entityName.trim().equals("")){
JOptionPane.showMessageDialog(this, "实体名不能为空!"); return ;
}
Pattern p2=Pattern.compile(fieldTypeRegex);
Matcher m2=p2.matcher(fieldsDeclare);
List<String> fieldTypeList=new ArrayList<String>();
while(m2.find()){
String fieldType= m2.group();
fieldTypeList.add(fieldType.trim());
}
String idJavaType="String";
if(fieldTypeList.get(0).startsWith("int")){
// idType="int";
idJavaType="int";
}
String idListType=null;
if(idJavaType.equals("int")){
idListType="Integer";
}else{
idListType="String";
}
String mapperInterfaceName=entityName+"Mapper";
String smallEntityName=firstLetterLowercase(entityName);
StringBuilder sb =new StringBuilder();
sb.append( "public interface "+mapperInterfaceName+" { \r\n " ) ;
sb.append( " public List<"+entityName+"> findAll(); \r\n " );
sb.append( " public int save("+entityName+" "+smallEntityName+"); \r\n " ) ;
sb.append( " public int update("+entityName+" "+smallEntityName+"); \r\n " ) ;
sb.append( " public int deleteById("+idJavaType+" id); \r\n " ) ;
sb.append( " public int deleteByIds("+idJavaType+"[] ids); \r\n " ) ;
sb.append( " public int deleteByIdList(List<"+idListType+"> idList); \r\n " ) ;
sb.append( " public "+entityName+" findById("+idJavaType+" id); \r\n ") ;
sb.append( " public List<"+entityName+"> findByIds("+idJavaType+"[] ids); \r\n ") ;
sb.append( " public List<"+entityName+"> findByIdList(List<"+idJavaType+"> idList); \r\n ") ;
sb.append( " public List<"+entityName+"> find"+entityName+"ListPage(Map<String,Object> param);\r\n " );
sb.append( " public int find"+entityName+"CountPage(Map<String,Object> param); \r\n " );
sb.append("\r\n");
sb.append( " public List<"+entityName+"> findListByParamMap(Map<String,Object> param); \r\n " );
sb.append( "} " );
textArea2.setText(sb.toString());
}
public void generateXML(){
String tableName=this.textField1.getText();//表名 t_book
String entityName=this.textField2.getText();//实体名(简单名称) Book
String namespace=this.textField3.getText();//命名空间 com.jelly.mvnweb2.mapper.BookMapper
String fieldsDeclare=this.textArea1.getText();
if(tableName==null||tableName.trim().equals("")){
JOptionPane.showMessageDialog(this, "表名不能为空!"); return ;
}
if(entityName==null||entityName.trim().equals("")){
JOptionPane.showMessageDialog(this, "实体名不能为空!"); return ;
}
if(namespace==null||namespace.trim().equals("")){
JOptionPane.showMessageDialog(this, "mapper命名空间不能为空!"); return ;
}
if(fieldsDeclare==null||fieldsDeclare.trim().equals("")){
JOptionPane.showMessageDialog(this, "表字段(列)声明不能为空!"); return ;
}
String fieldTypeRegex="(?<=`)\\s+[\\w\\(\\)]+";
Pattern p2=Pattern.compile(fieldTypeRegex);
Matcher m2=p2.matcher(fieldsDeclare);
List<String> fieldTypeList=new ArrayList<String>();
while(m2.find()){
String fieldType= m2.group();
fieldTypeList.add(fieldType.trim());
}
String idType="string";
if(fieldTypeList.get(0).startsWith("int")){
idType="int";
}
String fieldRegex="(?<=`)\\w+(?=`)";
Pattern p=Pattern.compile(fieldRegex);
Matcher m=p.matcher(fieldsDeclare);
List<String> fieldList=new ArrayList<String>();
while(m.find()){
String field=m.group();
fieldList.add(field);
}
StringBuilder sb=new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n")
.append("<!DOCTYPE mapper \r\n")
.append("PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \r\n")
.append("\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\r\n");
sb.append(" <mapper namespace=\""+namespace+"\" > "+ "\r\n");
String resultMapStr=buildResultMap(fieldList,entityName);
sb.append(resultMapStr);
sb.append(" <insert id=\"save\" parameterType=\""+entityName+"\"> \r\n");//save 语句
String insertCols= buildInsertCols(fieldList);
sb.append(" INSERT INTO "+tableName+"("+insertCols+") \r\n");
String insertVals=buildInsertVals(fieldList);
sb.append(" VALUES("+insertVals+") \r\n");
sb.append(" </insert>\r\n");
sb.append(" <select id=\"findAll\" resultType=\""+entityName+"\">\r\n "); //findAll 语句
sb.append(" SELECT * FROM "+tableName+" \r\n");
sb.append(" </select> \r\n");
sb.append(" <update id=\"update\" parameterType=\""+entityName+"\"> \r\n");// update
sb.append(" update "+tableName+" t "+"\r\n");
sb.append(" <set>\r\n");
String updateSetIf=buildUpdateSetIf(fieldList,fieldTypeList);
sb.append(updateSetIf);
sb.append(" </set>\r\n");
sb.append(" where t."+fieldList.get(0)+"=#{"+fieldList.get(0)+"} \r\n");
sb.append(" </update>\r\n");
sb.append(" <select id=\"findById\" parameterType=\""+idType+"\" resultType=\""+entityName+"\"> \r\n");//findById
sb.append(" SELECT * FROM `"+tableName+"` t WHERE t.`"+fieldList.get(0)+"`=#{_parameter} \r\n ");
sb.append(" </select> \r\n");
sb.append(" <delete id=\"deleteById\" parameterType=\""+idType+"\"> \r\n");//deleteById
sb.append(" DELETE FROM "+tableName+" WHERE "+fieldList.get(0)+"=#{_parameter} \r\n");
sb.append(" </delete> \r\n");
sb.append(" <delete id=\"deleteByIdList\" > \r\n ");
sb.append(" DELETE FROM "+tableName+" \r\n ");
sb.append(" WHERE "+fieldList.get(0)+" IN \r\n ");
sb.append(" <foreach collection=\"list\" index=\"index\" item=\"id\" open=\"(\" \r\n ");
sb.append(" close=\")\" separator=\",\"> \r\n ");
sb.append(" #{id} \r\n ");
sb.append(" </foreach> \r\n ");
sb.append(" </delete> \r\n ");
sb.append(" <delete id=\"deleteByIds\" > \r\n ");
sb.append(" DELETE FROM "+tableName+" \r\n ");
sb.append(" WHERE "+fieldList.get(0)+" IN \r\n ");
sb.append(" <foreach collection=\"array\" index=\"index\" item=\"id\" open=\"(\" \r\n ");
sb.append(" close=\")\" separator=\",\"> \r\n ");
sb.append(" #{id} \r\n ");
sb.append(" </foreach> \r\n ");
sb.append(" </delete> \r\n ");
sb.append(" <select id=\"findByIdList\" resultType=\""+entityName+"\"> \r\n ") ;
sb.append(" SELECT * FROM `"+tableName+"` a \r\n ") ;
sb.append(" WHERE a.`"+fieldList.get(0)+"` IN \r\n ") ;
sb.append(" <foreach collection=\"list\" index=\"index\" item=\"id\" open=\"(\" \r\n ") ;
sb.append(" close=\")\" separator=\",\"> \r\n ") ;
sb.append(" #{id} \r\n ") ;
sb.append(" </foreach> \r\n ") ;
sb.append(" </select> \r\n ");
sb.append(" <select id=\"findByIds\" resultType=\""+entityName+"\"> \r\n ") ;
sb.append(" SELECT * FROM `"+tableName+"` a \r\n ") ;
sb.append(" WHERE a.`"+fieldList.get(0)+"` IN \r\n ") ;
sb.append(" <foreach collection=\"array\" index=\"index\" item=\"id\" open=\"(\" \r\n ") ;
sb.append(" close=\")\" separator=\",\"> \r\n ") ;
sb.append(" #{id} \r\n ") ;
sb.append(" </foreach> \r\n ") ;
sb.append(" </select> \r\n ");
sb.append(" <select id=\"find"+entityName+"ListPage\" parameterType=\"map\" resultType=\""+entityName+"\">\r\n ");
sb.append(" SELECT * FROM `"+tableName+"` a \r\n ");
sb.append(" <where> \r\n ");
sb.append(" </where> \r\n ");
sb.append(" <if test=\"sortName!=null and sortName!='' and sortOrder!=null and sortOrder!='' \" > \r\n ");
sb.append(" ORDER BY ${sortName} ${sortOrder} \r\n ");
sb.append(" </if> \r\n ");
sb.append(" LIMIT #{startNum},#{pageSize} \r\n ");
sb.append(" </select> \r\n ");
sb.append(" <select id=\"find"+entityName+"CountPage\" parameterType=\"map\" resultType=\"int\"> \r\n ");
sb.append(" SELECT count(1) FROM `"+tableName+"` a \r\n ");
sb.append(" <where> \r\n ");
sb.append(" </where> \r\n ");
sb.append(" </select> \r\n ");
sb.append(" <select id=\"findListByParamMap\" parameterType=\"map\" resultType=\""+entityName+"\"> \r\n ");
sb.append(" SELECT * FROM `"+tableName+"` a \r\n ");
sb.append(" <where> \r\n ");
sb.append(" </where> \r\n ");
sb.append(" <if test=\"sortName!=null and sortName!='' and sortOrder!=null and sortOrder!=''\" > \r\n ");
sb.append(" ORDER BY ${sortName} ${sortOrder} \r\n ");
sb.append(" </if> \r\n ");
sb.append(" </select> \r\n");
sb.append("</mapper> \r\n");
textArea2.setText(sb.toString());
}
//生成bean
public void generateBean(){
String fieldsDeclare=this.textArea1.getText();
if(fieldsDeclare==null||fieldsDeclare.trim().equals("")){
JOptionPane.showMessageDialog(this, "表字段(列)声明不能为空!"); return ;
}
String fieldRegex="(?<=`)\\w+(?=`)";
Pattern p=Pattern.compile(fieldRegex);
Matcher m=p.matcher(fieldsDeclare);
List<String> fieldList=new ArrayList<String>();
while(m.find()){
String field=m.group();
fieldList.add(field);
}
String fieldTypeRegex="(?<=`)\\s+[\\w\\(\\)]+";
Pattern p2=Pattern.compile(fieldTypeRegex);
Matcher m2=p2.matcher(fieldsDeclare);
List<String> fieldTypeList=new ArrayList<String>();
while(m2.find()){
String fieldType= m2.group();
fieldTypeList.add(fieldType.trim());
}
StringBuilder sb=new StringBuilder();
for(int i=0;i<fieldList.size();i++){
String field=fieldList.get(i);
String fieldType=fieldTypeList.get(i);
if(fieldType.contains("int")){
sb.append("private Integer "+ field +";\r\n");
}else if(fieldType.equals("double")||fieldType.equals("float")){
sb.append("private Double "+ field +";\r\n");
}else if(fieldType.startsWith("decimal")){
sb.append("private String "+ field +";\r\n");
}else if(fieldType.endsWith("blob")){
sb.append("private byte[] "+ field +";\r\n");
}else{
sb.append("private String "+ field +";\r\n");
}
}
this.textArea2.setText(sb.toString());
}
public void clearXML(){
this.textArea2.setText("");
}
public void clearDeclare(){
this.textArea1.setText("");
this.textField1.setText("");
this.textField2.setText("");
this.textField3.setText("");
}
public void saveFile(){
// JOptionPane.showMessageDialog(this, "saveFile");
BufferedWriter writer=null;
try {
JFileChooser wjsave=null;
if(savedir!=null&&savedir.trim().length()>0){
wjsave=new JFileChooser(savedir);
}else{
wjsave=new JFileChooser();
}
wjsave.setDialogTitle("保存到文件");
FileNameExtensionFilter fef1=new FileNameExtensionFilter("文本文件","txt");
FileNameExtensionFilter fef2=new FileNameExtensionFilter("xml文件","xml");
wjsave.addChoosableFileFilter(fef1);
wjsave.addChoosableFileFilter(fef2);
wjsave.setDialogType(JFileChooser.SAVE_DIALOG);
int value= wjsave.showSaveDialog(null);
wjsave.setVisible(true);
if(value==JFileChooser.APPROVE_OPTION){//用户点击了保存
File savefile= wjsave.getSelectedFile();// 保存的文件
savedir= savefile.getParent();//将文件目录保存到成员变量
// writer=new BufferedWriter(new FileWriter(savefile));
writer = new BufferedWriter(new FileWriter(savefile));
String result=textArea2.getText();
writer.write(result);
}
} catch (Exception e) {
e.printStackTrace();
}
finally {//关流操作
try {
if (writer != null) {
writer.close();
}
}
catch (Exception e) {
System.out.println("BufferedWriter close IOException" + e.getStackTrace());
}
}
}
/**
* 生成 xxxResultMap 语句 中 id、result 列表
* @param fieldList 字段列表
* @return String
* @author jelly
*
*/
private String buildResultMap(List<String> fieldList,String entityName){
StringBuilder sb= new StringBuilder();
sb.append("<resultMap id=\""+entityName+"ResultMap\" type=\""+entityName+"\" >").append("\r\n");
sb.append(" <id column=\""+fieldList.get(0).toUpperCase()+"\" property=\""+fieldList.get(0)+"\"/>").append("\r\n");
for(int i=1;i<fieldList.size();i++){
sb.append(" <result column=\""+fieldList.get(i).toUpperCase()+"\" property=\""+fieldList.get(i)+"\" />").append("\r\n");
}
sb.append("</resultMap>").append("\r\n");
return sb.toString();
}
/**
* 生成insert 语句中的 column 列表
* @param fieldList
* @return
* @return String
* @author jelly
*
*/
private String buildInsertCols(List<String> fieldList) {
//`id`,`name`,`author`,`price`,`des`,`publisher`,`publishtime`,`createtime`,`imgBytes`,`htmlText`
StringBuilder sb= new StringBuilder();
for(int i=0;i<fieldList.size();i++){
String field= fieldList.get(i);
if(i==fieldList.size()-1){
sb.append(addBacktick(field));
}else{
sb.append(addBacktick(field)).append(",");
}
}
return sb.toString();
}
/**
* 生成insert 语句中的 value 列表
* @param fieldList
* @return
* @return String
* @author jelly
*
*/
private String buildInsertVals(List<String> fieldList) {
//#{id},#{name},#{author},#{price}, #{xxx}
StringBuilder sb=new StringBuilder();
for(int i=0;i<fieldList.size();i++){
String field= fieldList.get(i);
if(i==fieldList.size()-1){
sb.append("#{"+field+"}");
}else{
sb.append("#{"+field+"}").append(",");
}
}
return sb.toString();
}
private String addBacktick(String s){//添加反撇号
return "`"+s+"`";
}
/**
* 生成update 中的 if 列表
* @param fieldList
* @return
* @return String
* @author jelly
*/
private String buildUpdateSetIf(List<String> fieldList, List<String> fieldTypeList) {
StringBuilder sb=new StringBuilder();
for(int i=1;i<fieldList.size();i++){
String field= fieldList.get(i);
String fieldType=fieldTypeList.get(i);
if(fieldType.contains("int")){
sb.append(" <if test=\""+field+"!=null \" >"+"\r\n");
}else{
sb.append(" <if test=\""+field+"!=null and "+field+"!='' \" >"+"\r\n");
}
sb.append(" t."+field+"=#{"+field+"}, \r\n");
sb.append(" </if>"+"\r\n");
}
return sb.toString();
}
}
package com.jelly.mapperGen;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
public class FileUtils {
/**
* 判断文件的编码格式
* @param fileName 文件名字符串
* @return 文件编码格式
* @throws Exception
*/
public static String getFileEncoding(String fileName) throws Exception{
BufferedInputStream bin = null;
try {
bin= new BufferedInputStream( new FileInputStream(fileName));
int p = (bin.read() << 8) + bin.read(); String code = null; switch (p) { case 0xefbb: code = "UTF-8"; break; case 0xfffe: code = "Unicode"; break; case 0xfeff: code = "UTF-16BE"; break; default: code = "GBK"; } return code; } finally{ if(bin!=null){ bin.close(); } } } }
JFUtils.java
package com.jelly.mapperGen;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class JFUtils {
public static void positionCenter(JFrame f){
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension fsize = f.getSize();
if (fsize.height > screenSize.height){
fsize.height = screenSize.height;
}
if (fsize.width > screenSize.width){
fsize.width = screenSize.width;
}
f.setLocation((screenSize.width - fsize.width) / 2 ,(screenSize.height - fsize.height ) / 2 );
}
}
运行GenDemo 如下。 (也可以将项目导出为可运行的jar包,使用java命令运行程序)
表名:mysql数据库表的名称,如t_book
实体名(简单):表对应实体类名的简单名称,如Book
mapper命名空间:随便写个如aaa,生成后可修改的。
表字段(列)声明:表的列名声明,需要注意的是列名前后必须要有反撇号(`)包裹。仅含列的声明,不包括主、外键及索引声明等语句,并且默认认为第一列为主键列。
生成xml:指生成mapper的xml文件内容,可保存到文件
生成bean:指生产实体bean 的字段声明,eclipse中可按快捷键shift+alt+s,+r 生成getter 、setter方法。
生成接口:指生成mapper的java接口文件内容,可保存到文件。
生成的sql含基本的CRUD、分页查询、按id批量删除、按id批量查找等 。
百度网盘下载
mapperGen.jar
链接:https://pan.baidu.com/s/1gujXkiWvUG4URRbafJPhKg 密码:wees


阅读排行


Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1