Skip to content

Commit 10591cf

Browse files
committed
� Conflicts: � pom.xml
2 parents aa1a44e + 62f7b59 commit 10591cf

File tree

9 files changed

+511
-0
lines changed

9 files changed

+511
-0
lines changed

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
<module>springboot-mybatis-autoId</module>
3535
<module>springboot-code-authorization</module>
3636
<module>springboot-chaincontext</module>
37+
<module>springboot-generate-sqlscript</module>
3738
<module>springboot-mybatisplus-tenant</module>
3839
</modules>
3940
<parent>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
本文主要演示如何利用jdbc来批量新增数据库的表字段
2+
3+
其核心关键在于通过java.sql.DatabaseMetaData获取数据库表名称以及对应的数据库名称
4+
5+
本文提供2种方式新增数据库表字段
6+
7+
- 1、通过程序生成sql语句,并把sql语句写到文件中,然后在把生成的文件扔到数据库的客户端执行
8+
9+
- 2、通过程序生成的sql语句,直接在程序中执行sql
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>springboot-learning</artifactId>
7+
<groupId>com.github.lybgeek</groupId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>springboot-generate-sqlscript</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>mysql</groupId>
17+
<artifactId>mysql-connector-java</artifactId>
18+
</dependency>
19+
<dependency>
20+
<groupId>cn.hutool</groupId>
21+
<artifactId>hutool-all</artifactId>
22+
</dependency>
23+
<dependency>
24+
<groupId>org.apache.commons</groupId>
25+
<artifactId>commons-lang3</artifactId>
26+
</dependency>
27+
<dependency>
28+
<groupId>org.yaml</groupId>
29+
<artifactId>snakeyaml</artifactId>
30+
</dependency>
31+
</dependencies>
32+
33+
34+
</project>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.github.lybgeek.generate.properties;
2+
3+
import com.github.lybgeek.generate.util.YmlUtil;
4+
5+
public class DataSouceProperties {
6+
7+
private static String driverClassName;
8+
9+
private static String url;
10+
11+
private static String userName;
12+
13+
private static String password;
14+
15+
16+
static {
17+
driverClassName = YmlUtil.getValue("spring.datasource.driver-class-name").toString();
18+
url = YmlUtil.getValue("spring.datasource.url").toString();
19+
userName = YmlUtil.getValue("spring.datasource.username").toString();
20+
password = YmlUtil.getValue("spring.datasource.password").toString();
21+
}
22+
23+
24+
public static String getDriverClassName() {
25+
return driverClassName;
26+
}
27+
28+
public static void setDriverClassName(String driverClassName) {
29+
DataSouceProperties.driverClassName = driverClassName;
30+
}
31+
32+
public static String getUrl() {
33+
return url;
34+
}
35+
36+
public static void setUrl(String url) {
37+
DataSouceProperties.url = url;
38+
}
39+
40+
public static String getUserName() {
41+
return userName;
42+
}
43+
44+
public static void setUserName(String userName) {
45+
DataSouceProperties.userName = userName;
46+
}
47+
48+
public static String getPassword() {
49+
return password;
50+
}
51+
52+
public static void setPassword(String password) {
53+
DataSouceProperties.password = password;
54+
}
55+
56+
public static void main(String[] args) {
57+
System.out.println(DataSouceProperties.getDriverClassName());
58+
System.out.println(DataSouceProperties.getUrl());
59+
System.out.println(DataSouceProperties.getUserName());
60+
System.out.println(DataSouceProperties.getPassword());
61+
}
62+
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package com.github.lybgeek.generate.util;
2+
3+
4+
import cn.hutool.core.io.FileUtil;
5+
6+
import java.io.File;
7+
import java.io.IOException;
8+
import java.sql.*;
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
public class DBSqlScriptUtils {
14+
15+
public static void main(String[] args) throws Exception{
16+
// testWriteSqlStatement2File();
17+
testExecuteSqlStatements();
18+
}
19+
20+
21+
public static List<String> prepareSqlStatementWithStringFormat(boolean isForFiles) {
22+
String sql = "alter table %s ADD COLUMN create_time DATETIME COMMENT '创建时间',ADD COLUMN created_by_id BIGINT(20) DEFAULT NULL COMMENT '创建人id', ADD COLUMN update_time DATETIME COMMENT '修改时间', ADD COLUMN last_updated_by_id BIGINT(20) DEFAULT NULL COMMENT '修改人id'";
23+
List<String> sqlStatements = new ArrayList<>();
24+
Map<String, List<String>> dbTableNamesMap = DbUtils.INSTANCE.getDbTablesNamesMap();
25+
dbTableNamesMap.forEach((dbName,tableNames) -> {
26+
for (String tableName : tableNames) {
27+
String record = dbName + "." + tableName;
28+
String sqlStatement = String.format(sql, record);
29+
//如果是要写入文件,则每条生成的sql语句,需追加分号
30+
if(isForFiles){
31+
sqlStatement = sqlStatement + ";";
32+
}
33+
System.out.println(sqlStatement);
34+
sqlStatements.add(sqlStatement);
35+
36+
}
37+
38+
});
39+
return sqlStatements;
40+
41+
}
42+
43+
44+
/**
45+
*
46+
*
47+
* SELECT
48+
* GROUP_CONCAT(
49+
* 'alter table ',
50+
* table_schema,
51+
* '.',
52+
* table_name,
53+
* ' ADD COLUMN create_time DATETIME COMMENT \'创建时间\',ADD COLUMN created_by_id BIGINT(20) DEFAULT NULL COMMENT \'创建人id\', ADD COLUMN update_time DATETIME COMMENT \'修改时间\', ADD COLUMN last_updated_by_id BIGINT(20) DEFAULT NULL COMMENT \'修改人id\'' SEPARATOR ""
54+
* ) AS sqlStatement
55+
* FROM
56+
* information_schema.tables
57+
* WHERE table_schema = 'db_user'
58+
* AND table_name = 't_user'
59+
* 准备要执行的sql脚本语句
60+
* @param isForFiles 如果是要写入文件,则每条生成的sql语句,需追加分号
61+
* @return
62+
*/
63+
public static List<String> prepareSqlStatement(boolean isForFiles){
64+
List<String> sqlStatements = new ArrayList<>();
65+
String sql = "\n" +
66+
"SELECT\n" +
67+
" GROUP_CONCAT(\n" +
68+
" 'alter table ',\n" +
69+
" table_schema,\n" +
70+
" '.',\n" +
71+
" table_name,\n" +
72+
" ' ADD COLUMN create_time DATETIME COMMENT \\'创建时间\\',ADD COLUMN created_by_id BIGINT(20) DEFAULT NULL COMMENT \\'创建人id\\', ADD COLUMN update_time DATETIME COMMENT \\'修改时间\\', ADD COLUMN last_updated_by_id BIGINT(20) DEFAULT NULL COMMENT \\'修改人id\\'' SEPARATOR \"\"\n" +
73+
" ) AS sqlStatement \n" +
74+
"FROM\n" +
75+
" information_schema.tables\n" +
76+
"WHERE table_schema = ?\n" +
77+
" AND table_name = ? ";
78+
79+
Map<String, List<String>> dbTableNamesMap = DbUtils.INSTANCE.getDbTablesNamesMap();
80+
dbTableNamesMap.forEach((dbName,tableNames) -> {
81+
for (String tableName : tableNames) {
82+
try {
83+
PreparedStatement ps = DbUtils.INSTANCE.getConnection().prepareStatement(sql);
84+
ps.setString(1,dbName);
85+
ps.setString(2,tableName);
86+
ResultSet rs = ps.executeQuery();
87+
while(rs.next()){
88+
String sqlStatement = rs.getString("sqlStatement");
89+
//如果是要写入文件,则每条生成的sql语句,需追加分号
90+
if(isForFiles){
91+
sqlStatement = sqlStatement + ";";
92+
}
93+
System.out.println(sqlStatement);
94+
sqlStatements.add(sqlStatement);
95+
}
96+
} catch (SQLException throwables) {
97+
throwables.printStackTrace();
98+
}
99+
}
100+
101+
});
102+
103+
DbUtils.INSTANCE.close();
104+
return sqlStatements;
105+
}
106+
private static void printTableColumns() {
107+
//存放当前表的字段
108+
List<String> fields= new ArrayList<>();
109+
//存放当前表的字段类型
110+
List<String> fieldstype = new ArrayList<>();
111+
Map<String, List<String>> dbTableNamesMap = DbUtils.INSTANCE.getDbTablesNamesMap();
112+
113+
dbTableNamesMap.forEach((dbName,tableNames) -> {
114+
for (String tableName : tableNames) {
115+
String record = dbName + "." + tableName;
116+
String sql = "select * from " + record;
117+
try {
118+
PreparedStatement ps = DbUtils.INSTANCE.getConnection().prepareStatement(sql);
119+
ResultSet rstable = ps.executeQuery();
120+
//结果集元数据
121+
ResultSetMetaData meta = rstable.getMetaData();
122+
//表列数量
123+
int columeCount=meta.getColumnCount();
124+
for (int i=1;i<=columeCount;i++)
125+
{
126+
fields.add(meta.getColumnName(i));
127+
fieldstype.add(meta.getColumnTypeName(i));
128+
129+
}
130+
System.out.println("表"+record+",字段: "+fields);
131+
System.out.println("表"+record+",字段类型: "+fieldstype);
132+
} catch (SQLException throwables) {
133+
throwables.printStackTrace();
134+
}
135+
136+
}
137+
});
138+
139+
DbUtils.INSTANCE.close();
140+
}
141+
142+
public static void writeSqlStatement2File(List<String> sqlStatements,String filePath){
143+
144+
try {
145+
File file = new File(filePath);
146+
if(!file.exists()){
147+
file.createNewFile();
148+
}
149+
FileUtil.writeUtf8Lines(sqlStatements,file);
150+
System.out.println("数据库脚本写入"+filePath+"成功");
151+
} catch (IOException e) {
152+
e.printStackTrace();
153+
System.out.println("数据库脚本写入"+filePath+"失败");
154+
}
155+
156+
157+
}
158+
159+
public static void executeSqlStatements(List<String> sqlStatements){
160+
try {
161+
Statement statement = DbUtils.INSTANCE.getConnection().createStatement();
162+
for (String sqlStatement : sqlStatements) {
163+
statement.addBatch(sqlStatement);
164+
}
165+
statement.executeBatch();
166+
} catch (SQLException throwables) {
167+
throwables.printStackTrace();
168+
}
169+
}
170+
171+
private static void testWriteSqlStatement2File(){
172+
List<String> sqlStatements = prepareSqlStatement(true);
173+
writeSqlStatement2File(sqlStatements,"E:\\db.sql");
174+
}
175+
176+
private static void testExecuteSqlStatements(){
177+
List<String> sqlStatements = prepareSqlStatementWithStringFormat(false);
178+
executeSqlStatements(sqlStatements);
179+
}
180+
181+
182+
}
183+
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.github.lybgeek.generate.util;
2+
3+
import cn.hutool.core.util.ObjectUtil;
4+
import cn.hutool.db.DbUtil;
5+
import com.github.lybgeek.generate.properties.DataSouceProperties;
6+
7+
import java.sql.*;
8+
import java.util.ArrayList;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
public enum DbUtils {
14+
15+
INSTANCE;
16+
17+
private Connection connection;
18+
19+
public Connection getConnection(){
20+
try {
21+
Class.forName(DataSouceProperties.getDriverClassName());
22+
connection = DriverManager.getConnection(DataSouceProperties.getUrl(),DataSouceProperties.getUserName(),DataSouceProperties.getPassword());
23+
} catch (Exception e) {
24+
e.printStackTrace();
25+
}
26+
27+
return connection;
28+
}
29+
30+
public void close(){
31+
if(ObjectUtil.isNotNull(connection)){
32+
try {
33+
connection.close();
34+
} catch (SQLException throwables) {
35+
throwables.printStackTrace();
36+
}
37+
}
38+
}
39+
40+
/**
41+
* 获取数据库下的所有数据库表名
42+
*
43+
* @return Map<String, List<String>> key为数据库名称,value为该数据库下的所有表名
44+
*/
45+
public Map<String, List<String>> getDbTablesNamesMap(){
46+
Map<String, List<String>> dbTableNamesMap = new HashMap<>();
47+
try {
48+
//获取数据库的元数据
49+
DatabaseMetaData dbMetaData = getConnection().getMetaData();
50+
//从元数据中获取到所有的表名
51+
ResultSet rs = dbMetaData.getTables(null, null, null,new String[] { "TABLE" });
52+
List<String> tableNames;
53+
while(rs.next()) {
54+
String tableName = rs.getString("TABLE_NAME");
55+
String curTableDbName = rs.getString("TABLE_CAT");
56+
String tableNameType = rs.getString("TABLE_TYPE");
57+
//表模式(可能为空),在oracle中获取的是命名空间
58+
String tableNameSchema = rs.getString("TABLE_SCHEM");
59+
String tableNameRemark = rs.getString("REMARKS");
60+
System.out.println("表名: " + tableName + ",表所属数据库: " + curTableDbName + ",表类型: " + tableNameType + ",表模式: " + tableNameSchema + ",表备注: " + tableNameRemark);
61+
//跳过mysql自带的系统库
62+
if("sys".equalsIgnoreCase(curTableDbName)){
63+
continue;
64+
}
65+
if(dbTableNamesMap.containsKey(curTableDbName)){
66+
tableNames = dbTableNamesMap.get(curTableDbName);
67+
}else{
68+
tableNames = new ArrayList<>();
69+
}
70+
tableNames.add(tableName);
71+
dbTableNamesMap.put(curTableDbName,tableNames);
72+
}
73+
} catch (SQLException throwables) {
74+
throwables.printStackTrace();
75+
}
76+
77+
close();
78+
return dbTableNamesMap;
79+
}
80+
81+
public static void main(String[] args) {
82+
Map<String, List<String>> dbTableNamesMap = DbUtils.INSTANCE.getDbTablesNamesMap();
83+
System.out.println(dbTableNamesMap);
84+
}
85+
86+
}

0 commit comments

Comments
 (0)