众所周知,我们平常在做项目的时候,数据库中复杂的表和列导致我们手写很破烦的实体类,虽然都是工具生成,但是属性多了,也会感觉到很破烦!!!今天我们来做一个简单的数据库表生成相应的实体类!!!
主要依据四条sql语句:
# 查询所有的数据库
SELECT schema_name FROM information_schema.SCHEMATA;
# 查询数据库中表的名字
SELECT table_name FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'students';
# 获取列名和类型
SELECT column_name,data_type FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'students' AND table_name='score';
# 查询外键关联表和外键列名
SELECT column_name, referenced_table_name FROM information_schema.KEY_COLUMN_USAGE WHERE table_schema = 'scott' AND table_name='emp'
AND constraint_name = (SELECT constraint_name FROM TABLE_CONSTRAINTS WHERE table_schema = 'scott' AND table_name='emp' AND constraint_type='Foreign key');
1、创建并导入properties配置文件和jar包
- 1、在项目下创建proFile文件夹,导入DBCP连接池配置文件mysql.dbcp.properties
代码如下:
########DBCP配置文件##########
#非自动提交
defaultAutoCommit=false
#驱动名
driverClassName=com.mysql.jdbc.Driver
#url
url=jdbc:mysql://127.0.0.1:3306/information_schema
#用户名
username=root
#密码
password=6831245
#初始连接数
initialSize=1
#最大活跃数
maxTotal=30
#最大空闲数
maxIdle=10
#最小空闲数
minIdle=1
#最长等待时间(毫秒)
maxWaitMillis=5000
#程序中的连接不使用后是否被连接池回收(该版本要使用removeAbandonedOnMaintenance和removeAbandonedOnBorrow)
#removeAbandoned=true
removeAbandonedOnMaintenance=true
removeAbandonedOnBorrow=true
#连接在所指定的秒数内未使用才会被删除(秒)
removeAbandonedTimeout=5
#连接代码
#Properties ps = new Properties();
#使用类加载器在项目的src目录下加载指定文件名的文件,来封装输入流
#InputStream fis =ConnUtil.class.getClassLoader().getResourceAsStream("dbcp.properties");
#也可以使用文件输入流加载项目路径下的文件,封装为文件输入流对象键盘输入对象
#FileInputStream fis = new FileInputStream("项目下文件路径/mysql.dbcp.properties");
#ps.load(fis);
#DataSource ds = BasicDataSourceFactory.createDataSource(ps);
#conn = ds.getConnection();
- 2、导入4个相关jar包
2、创建MVC结构的项目结构
3、创建view层
代码如下: MainView.java
package com.yueqian.entityCreater.view;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import com.yueqian.entityCreater.controller.MainViewLis;
import com.yueqian.entityCreater.model.dao.DBDao;
public class MainView extends JFrame{
//创建数据库选择下拉框
private JComboBox<String> dbBox = null;
//创建数据库表的列表
private JList<String> tabLis = null;
//创建生成实体类按钮
private JButton createBtn = null;
//获取所有数据库名称
private Vector<String> dbNames = null;
//获取所有表名称
private Vector<String> tabNames = null;
public MainView() {
super("Entity Creater");
this.setSize(280,300);
this.setLocationRelativeTo(null);
//添加组件
addComponent();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
private void addComponent() {
dbNames = DBDao.getInstance().getDbNames();
//建立数据库下拉框
dbBox = new JComboBox<String>(dbNames);
//创建面板
JPanel dbPan = new JPanel(new FlowLayout(FlowLayout.LEFT,10,10));
//添加标签到面板
dbPan.add(new JLabel("数据库名称:"));
//添加数据库下拉列表框
dbPan.add(dbBox);
//添加面板到北部
this.add(dbPan,BorderLayout.NORTH);
tabNames = DBDao.getInstance().getTableNames(dbNames.get(0));
//添加表名信息到展示列表
this.tabLis = new JList<String>(tabNames);
//创建表名面板 (使用边界布局管理器)
JPanel tabPan = new JPanel(new BorderLayout());
//产生边线
tabPan.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),"表信息:"));
//将表格列表包裹进面板中,有滚动条
JScrollPane js = new JScrollPane(tabLis);
tabPan.add(js);
//将表格面板添加到窗口
this.add(tabPan);
//构造按钮
createBtn = new JButton("生成Entity");
//创建按钮面板
JPanel btnPan = new JPanel(new FlowLayout(FlowLayout.LEADING,10,10));
//将按钮添加到按钮面板
btnPan.add(createBtn);
//添加面板到南部
this.add(btnPan,BorderLayout.SOUTH);
//添加监听器
MainViewLis mvLis = new MainViewLis(this);
this.dbBox.addItemListener(mvLis);
this.createBtn.addActionListener(mvLis);
}
public JComboBox<String> getDbBox() {
return dbBox;
}
public void setDbBox(JComboBox<String> dbBox) {
this.dbBox = dbBox;
}
public JList<String> getTabLis() {
return tabLis;
}
public void setTabLis(JList<String> tabLis) {
this.tabLis = tabLis;
}
public Vector<String> getDbNames() {
return dbNames;
}
public void setDbNames(Vector<String> dbNames) {
this.dbNames = dbNames;
}
public Vector<String> getTabNames() {
return tabNames;
}
public void setTabNames(Vector<String> tabNames) {
this.tabNames = tabNames;
}
}
4、创建DBCPProUtil类(配置文件连接池连接数据库)
代码如下: DBCPProUtil.java
package com.yueqian.entityCreater.util;
/**
* 配置文件方式连接池工具类
* @author LinChi
*
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
public class DBCPProUtil {
private static BasicDataSource bs;
/**
* 配置文件方式连接数据库
* @return
*/
public static Connection getConnection() {
//创建类加载器方式文件输入流对象
FileInputStream fis = null;
if(bs == null) {
//创建属性对象 从属性文件创建属性信息
Properties ps = new Properties();
try {
//将属性文件封装成文件输入流
//可以使用文件输入流加载项目路径下的文件,封装为文件输入流对象键盘输入对象
// fis = new FileInputStream("dbproperties/mysql.dbcp.properties");
//也可以使用类加载器在项目的src目录下加载指定文件名的文件,来封装输入流
//注意:使用类加载机制记载配置文件,配置文件必须为src目录下
// fis = DBCPProUtil.class.getClassLoader().getResourceAsStream("mysql.dbcp.properties");
fis = new FileInputStream("proFile/mysql.dbcp.properties");
//让属性文件通过属性对象读取文件输入流中的属性信息
ps.load(fis);
//使用DBCP工厂类创建核心类BasicDataSource,将属性文件对象出入
//自动设置属性信息配置数据源 (工厂模式)
//注意:属性文件中的key大小写是固定的,利用反射自动获取key值
bs = BasicDataSourceFactory.createDataSource(ps);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
return bs.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 关闭连接池对象
*/
public static void closeDbcp() {
if(bs != null) {
try {
bs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 关闭数据库
* @param conn 连接
* @param st 处理sql对象
* @param rs 查询结果集
*/
public static void closeAll(Connection conn,Statement st,ResultSet rs) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(st != null) {
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
5、创建Model层
1、创建持久层
代码如下: DBDao.java
package com.yueqian.entityCreater.model.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import javax.swing.JOptionPane;
import com.yueqian.entityCreater.util.DBCPProUtil;
/**
* 数据持久层
* @author LinChi
*
*/
public class DBDao {
//使用单例模式
private static DBDao dbDao = null;
private DBDao() {
}
public static DBDao getInstance() {
if(dbDao == null) {
dbDao = new DBDao();
}
return dbDao;
}
/**
* 查询所有数据库名
*/
public Vector<String> getDbNames(){
//创建vector
Vector<String> vector = new Vector<String>();
//创建sql语句
String sql = "SELECT schema_name FROM information_schema.SCHEMATA";
//获得连接
Connection conn = DBCPProUtil.getConnection();
//判断是否连接成功
if(conn == null) {
JOptionPane.showMessageDialog(null, "数据库连接失败,请检查连接文件,在proFile/mysql.dbcp.properties中!","错误",JOptionPane.ERROR_MESSAGE);
return vector;
}
//创建预处理sql对象
PreparedStatement pst = null;
//执行结果集
ResultSet rs = null;
try {
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
while(rs.next()) {
vector.add(rs.getString(1));
}
//提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
//回滚事务
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}finally {
DBCPProUtil.closeAll(conn, pst, rs);
}
return vector;
}
/**
* 查询指定数据库中表的名字
*/
public Vector<String> getTableNames(String dbName){
//创建vector
Vector<String> vector = new Vector<String>();
//创建sql语句
String sql = "SELECT table_name FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?";
//获得连接
Connection conn = DBCPProUtil.getConnection();
//判断是否连接成功
if(conn == null) {
JOptionPane.showMessageDialog(null, "数据库连接失败,请检查连接文件,在proFile/mysql.dbcp.properties中!","错误",JOptionPane.ERROR_MESSAGE);
return vector;
}
//创建预处理sql对象
PreparedStatement pst = null;
//设置参数
//执行结果集
ResultSet rs = null;
try {
pst = conn.prepareStatement(sql);
pst.setString(1, dbName);
rs = pst.executeQuery();
while(rs.next()) {
vector.add(rs.getString(1));
}
//提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
//回滚事务
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}finally {
DBCPProUtil.closeAll(conn, pst, rs);
}
return vector;
}
/**
* 查询指定数据库中列的信息
*/
public Map<String,String> getTabColumns(String dbName,String tabName){
//创建Map
Map<String,String> map = new HashMap<String,String>();
//创建sql语句
String sql = "SELECT column_name,data_type FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND table_name=?";
//获得连接
Connection conn = DBCPProUtil.getConnection();
//判断是否连接成功
if(conn == null) {
JOptionPane.showMessageDialog(null, "数据库连接失败,请检查连接文件,在proFile/mysql.dbcp.properties中!","错误",JOptionPane.ERROR_MESSAGE);
return map;
}
//创建预处理sql对象
PreparedStatement pst = null;
//执行结果集
ResultSet rs = null;
try {
pst = conn.prepareStatement(sql);
pst.setString(1, dbName);
pst.setString(2,tabName);
rs = pst.executeQuery();
while(rs.next()) {
map.put(rs.getString(1),rs.getString(2));
}
//提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
//回滚事务
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}finally {
DBCPProUtil.closeAll(conn, pst, rs);
}
return map;
}
}
2、创建实体类工具
代码如下:CreateEntityUtil.java
package com.yueqian.entityCreater.model.dao;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.Map;
import javax.swing.JOptionPane;
import com.yueqian.entityCreater.view.MainView;
/**
* 创建实体类工具
*
* @author LinChi
*
*/
public class CreateEntityUtil {
private static final String SPACE = " ";
public static void writerEntityFile(String tabName, Map<String, String> colMap) {
// 创建输出文件
File outputDir = new File("output");
// 判断文件是否存在
if (!outputDir.isDirectory()) {
outputDir.mkdir();
}
// 获得类名
String classStr = getClassStr(tabName, colMap);
// 获取文件名
String fileName = getClassName(tabName) + ".java";
// 创建写出文件
File javaFile = new File(outputDir, fileName);
// 判断文件是否存在并覆盖
if (javaFile.exists()) {
if (JOptionPane.NO_OPTION == JOptionPane.showConfirmDialog(null, "所选" + fileName + "文件已经存在,是否覆盖?", "提示",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)) {
return;
}
}
// 输出流
FileOutputStream out = null;
OutputStreamWriter osw = null;
try {
out = new FileOutputStream(javaFile);
osw = new OutputStreamWriter(out);
osw.write(classStr.toCharArray());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 获取所有Map字符
*
* @param tabName
* @param colMap
* @return
*/
private static String getClassStr(String tabName, Map<String, String> colMap) {
// 获取类名
String className = getClassName(tabName);
// 定义保存数据的StringBuffer
StringBuffer sb = new StringBuffer();
// 定义getset方法
StringBuffer sbuf = new StringBuffer();
sb.append("public class ").append(className).append(" {").append("\r\n");
for (Map.Entry<String, String> entry : colMap.entrySet()) {
// 获取列的类型
String dbType = entry.getValue();
// 将列的类型转换为java类型
String javaType = getJavaType(dbType);
// 获取列名
String dbColumnName = entry.getKey();
// 将列名转换为属性名
String filedName = getColumnName(dbColumnName);
sb.append(SPACE).append("private ").append(javaType).append(" ").append(filedName).append(";\r\n");
// 添加get和set方法
sbuf.append(getMethod(filedName, javaType));
sbuf.append(setMethod(filedName, javaType));
}
sb.append(sbuf).append("}");
return sb.toString();
}
/**
* 添加外键列的属性
*/
// private static String getForeign(String foreignName) {
// if(isStringEntity(foreignName)) {
// return "";
// }
// //将首字母大写
// String firstStr = String.valueOf(foreignName.charAt(0)).toUpperCase();
// if(foreignName.trim().length() == 1) {
// return firstStr+"Entity";
// }
// return firstStr+foreignName.substring(1)+"Entity";
// }
/**
* 添加get方法
*/
private static String getMethod(String fieldName, String javaType) {
if (isStringEntity(fieldName, javaType)) {
return "";
}
StringBuffer sb = new StringBuffer();
sb.append(SPACE).append("public ").append(javaType).append(" get");
// 如果属性第二个字母为小写,则将第三个字母为大写,将属性名首字母大写
if (fieldName.charAt(1) >= 'a' && fieldName.charAt(1) <= 'z') {
sb.append(String.valueOf(fieldName.charAt(0)).toUpperCase());
} else {
sb.append(fieldName.charAt(0));
}
// 判断属性名是否为1个字符
if (fieldName.length() != 1) {
sb.append(fieldName.substring(1));
}
sb.append("() {\r\n").append(SPACE);
sb.append(SPACE).append("return this.").append(fieldName).append(";\r\n");
sb.append(SPACE).append("}\r\n");
return sb.toString();
}
/**
* set方法
*/
private static String setMethod(String fieldName, String javaType) {
if (isStringEntity(fieldName, javaType)) {
return "";
}
StringBuffer sb = new StringBuffer();
sb.append(SPACE).append("public void set");
// 如果属性第二个字母为小写,则将第三个字母为大写,将属性名首字母大写
if (fieldName.charAt(1) >= 'a' && fieldName.charAt(1) <= 'z') {
sb.append(String.valueOf(fieldName.charAt(0)).toUpperCase());
} else {
sb.append(fieldName.charAt(0));
}
if (fieldName.length() != 1) {
sb.append(fieldName.substring(1));
}
sb.append("(").append(javaType).append(SPACE).append(fieldName).append("){\r\n");
sb.append(SPACE).append(SPACE).append("this.").append(fieldName).append(" = ").append(fieldName)
.append(";\r\n");
sb.append(SPACE).append("}\r\n");
return sb.toString();
}
/**
* 将dbType转换为javaType
*
* @param dbType
* @return
*/
private static String getJavaType(String dbType) {
if ("int".equalsIgnoreCase(dbType) || "Integer".equalsIgnoreCase(dbType)) {
return "Integer";
}
if ("float".equalsIgnoreCase(dbType) || "double".equalsIgnoreCase(dbType)
|| "decimal".equalsIgnoreCase(dbType)) {
return "Double";
}
if ("varchar".equalsIgnoreCase(dbType) || "char".equalsIgnoreCase(dbType)) {
return "String";
}
if ("date".equalsIgnoreCase(dbType) || "datetime".equalsIgnoreCase(dbType)) {
return "java.util.date";
}
if ("blob".equalsIgnoreCase(dbType)) {
return "byte[]";
}
return "";
}
/**
* 根据表名获取类名
*
* @param tabName
* @return
*/
private static String getClassName(String tabName) {
if (isStringEntity(tabName)) {
return "";
}
// 将表中带_的字符去掉
tabName = getColumnName(tabName);
// 将首字母大写
String firstStr = String.valueOf(tabName.charAt(0)).toUpperCase();
// 判断是否单个字符为表名
if (tabName.trim().length() == 1) {
return firstStr + "Entity";
}
return firstStr + tabName.substring(1) + "Entity";
}
/**
* 将列名转换为属性名
*
* @param tabName
* @return
*/
private static String getColumnName(String colName) {
if (isStringEntity(colName)) {
return "";
}
// 将所有字段名转换为小写
colName = colName.toLowerCase();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < colName.length(); i++) {
String charStr = String.valueOf(colName.charAt(i));
if ("_".equals(charStr)) {
i++;
// 过滤是否以_结尾
if (i >= colName.length()) {
break;
}
charStr = String.valueOf(colName.charAt(i)).toUpperCase();
}
sb.append(charStr);
}
return sb.toString();
}
private static boolean isStringEntity(String... colName) {
for (int i = 0; i < colName.length; i++) {
if (colName[i] == null || colName[i].trim().length() <= 0) {
return true;
}
}
return false;
}
}
6、创建controller层
创建监听器
代码如下:MainViewLis.java
package com.yueqian.entityCreater.controller;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.swing.JOptionPane;
import com.yueqian.entityCreater.model.dao.CreateEntityUtil;
import com.yueqian.entityCreater.model.dao.DBDao;
import com.yueqian.entityCreater.view.MainView;
/**
* 主窗口监听器
* @author LinChi
*
*/
public class MainViewLis implements ActionListener,ItemListener{
private MainView mainView;
public MainViewLis(MainView mainView) {
super();
this.mainView = mainView;
}
/**
* 变更所选内容
*/
@Override
public void itemStateChanged(ItemEvent e) {
//获取数据库名称
String dbName = mainView.getDbBox().getSelectedItem().toString();
//获取该库对应的表信息
Vector<String> tableNames = DBDao.getInstance().getTableNames(dbName);
//清理mainView上的表信息
mainView.getTabNames().clear();
//将选择的表的信息添加到窗口中
mainView.getTabNames().addAll(tableNames);
//刷新重绘数据表列表
mainView.getTabLis().repaint();
}
@Override
public void actionPerformed(ActionEvent e) {
//获取数据库名
String dbName = mainView.getDbBox().getSelectedItem().toString();
//获取表名
List<String> tableList = mainView.getTabLis().getSelectedValuesList();
//判断是否选择表文件
if(tableList.isEmpty()) {
JOptionPane.showMessageDialog(null, "请先选择需要导出的表!","错误",JOptionPane.ERROR_MESSAGE);
return;
}
//根据表名称和库名称获取列信息 Map<表名,Map<列名,列类型>>
Map<String,Map<String,String>> map = new HashMap<String,Map<String,String>>();
//循环取出所有选择的表的列信息
for (String tableName : tableList) {
Map<String,String> tabColMap = DBDao.getInstance().getTabColumns(dbName,tableName);
map.put(tableName, tabColMap);
}
//循环输出entity
for(Map.Entry<String,Map<String,String>> entrty:map.entrySet()) {
CreateEntityUtil.writerEntityFile(entrty.getKey(), entrty.getValue());
}
JOptionPane.showMessageDialog(null,"执行完毕!");
}
}
7、创建程序入口类
代码如下:App.java
package com.yueqian.entityCreater.app;
import com.yueqian.entityCreater.view.MainView;
public class App {
public static void main(String[] args) {
new MainView();
}
}
8、效果图
选择数据库
一键生成
生成实体类如下:
9、将项目导成jar文件,方便执行
- 1、项目右键-> Export -> Runnable JAR file ->选择位置finash
- 2、将proFile文件夹复制到和jar包平级的位置(文件夹下有properties配置文件)
- 3、如果导出的是jar包,则可直接运行
- 4、如果是压缩文件,则新建文本->后缀名改为.bat(批处理文件),内容写入java -jar entityCreater.jar,记得按个回车
- 5、执行批处理文件即可执行
好了!小伙伴们,今天的分享就到此了!这儿没有按照查询到外键生成相应的实体类,将外键对应的实体类通过属性传递。后面会逐步添加此功能,感兴趣的小伙伴可以自己评论添加哦!这样我们就不用自己手写烦人的实体类了!!!