工具类:
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
/**
* entity 表创建MySQL语句生成类,创建的类必须是添加了JPA注解的类
*
* @author zql
*
*/
public class MySQLTableCreator<T> {
public static void main(String[] args) throws Exception {
// 注意:定义实体类成员变量时请使用包装类
new MySQLTableCreator<>().doScanerAndPrintSQL("test.entity");
}
/**
* 定义一个类泛型
*/
private Class<T> entityClass=null;
/**
* 表名
*/
private String tableName=null;
/**
* 主键对应的实体的成员变量名称
*/
private String primaryKeyFieldName=null;
/**
* 数据库主键列名
*/
private String primaryKeyColumnName=null;
/**
* 实体成员变量名称(key)与数据库列名(value) 键值对
*/
private Map<String,String> fieldColumnMap=null;
/**
* 实体成员变量名称数组
*/
private String[] fieldNames=null;
/**
* 数据库列名数组
*/
private String[] columnNames=null;
/**
* 数据库列长
*/
private int[] columnLength=null;
/**
* 经过处理的数据库列名,可直接用于拼接sql语句(例如 MySql 关键字desc -> `desc` )
*/
private String[] columnNamesForSQL=null;
/**
* 实体成员变量名称(key)与数据类型(value)键值对
*/
private Map<String,Class<?>> fieldType=new HashMap<String,Class<?>>();
/**
* 实体成员数据类型(key)与数据库数据类型(value)键值对
*/
private static Map<String,String> t = null;
static {
t=new HashMap<String,String>();
t.put("java.lang.Long", "BIGINT");
t.put("java.lang.String", "VARCHAR");
t.put("java.lang.Integer", "INTEGER");
t.put("java.util.Date", "DATE");
t.put("java.lang.Double", "DOUBLE");
t.put("java.lang.Boolean", "BIT");
// DECIMAL(P,D)表示列可以存储D位小数的P位数。十进制列的实际范围取决于精度和刻度。
t.put("java.math.BigDecimal", "DECIMAL(18,8) DEFAULT(0)");
}
public MySQLTableCreator() {}
/**
* @param entityClass 添加了JPA注解的类
*/
public MySQLTableCreator(Class<T> entityClass) {
this.entityClass=entityClass;
// 数据库表名
this.tableName=this.entityClass.getAnnotation(Table.class).name();
parseFieldAndColumn();
}
/**
* 解析字段和列名,并存入数组
*/
private void parseFieldAndColumn() {
this.fieldColumnMap = new LinkedHashMap<String, String>();
getColumnFromSelfAndParent(this.entityClass, fieldColumnMap);
int c = this.fieldColumnMap.size();
this.fieldNames = new String[c];
this.columnNames = new String[c];
this.columnNamesForSQL = new String[c];
this.columnLength = new int[c];
// 索引计数器
int counter = 0;
String columnName = null;
for (Map.Entry<String, String> e : this.fieldColumnMap.entrySet()) {
this.fieldNames[counter] = e.getKey();
columnName = e.getValue().substring(0, e.getValue().indexOf(","));
int len = Integer.parseInt(e.getValue().substring(e.getValue().indexOf(",") + 1));
len = len > 65532 ? 65532 : len;
this.columnNames[counter] = columnName;
this.columnLength[counter] = len;
this.columnNamesForSQL[counter] = "`" + columnName + "`";
++counter;
}
}
/**
* 获取继承的父类
*
* @param clz
* @param fieldColumnMap
*/
private void getColumnFromSelfAndParent(Class<?> clz, Map<String,String> fieldColumnMap) {
getColumn(clz, fieldColumnMap);
if (clz.getSuperclass() != Object.class) {
getColumnFromSelfAndParent(clz.getSuperclass(), fieldColumnMap);
}
}
/**
* 获取列
*
* @param clz
* @param fieldColumnMap
*/
private void getColumn(Class<?> clz,Map<String,String> fieldColumnMap){
// 获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
Field[] fields = clz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
// 此方法返回该元素的注解在此元素的指定注释类型(如果存在),否则返回null
Column ann = field.getAnnotation(Column.class);
if (ann != null) {
String fieldName = field.getName();
// 数据库表列名
String columnName = ann.name();
fieldColumnMap.put(fieldName, columnName + "," + ann.length());
this.fieldType.put(fieldName, field.getType());
Id idAnn = field.getAnnotation(Id.class);
// 主键不等于空
if (idAnn != null) {
this.primaryKeyFieldName = field.getName();
this.primaryKeyColumnName = ann.name();
}
}
}
}
/**
* 扫描包并打印表创建语句
*
* @param basicPackage
* @throws Exception
*/
public void doScanerAndPrintSQL(String basicPackage) throws Exception {
String packageSearchPath = "classpath*:" + basicPackage.replace('.', '/') + "/" + "*.class";
PathMatchingResourcePatternResolver pmr = new PathMatchingResourcePatternResolver();
Resource[] rs = pmr.getResources(packageSearchPath);
for (Resource r : rs) {
CachingMetadataReaderFactory ss = new CachingMetadataReaderFactory();
MetadataReader ma = ss.getMetadataReader(r);
Class<?> clazz = Class.forName(ma.getClassMetadata().getClassName());
if (clazz.getAnnotation(Table.class) != null) {
new MySQLTableCreator<>(clazz).printlnTableCreateSQL();
}
}
}
/**
* 生成数据库表创建语句
*
* @return
*/
public String generateTableCreateSQL() {
StringBuilder sb = new StringBuilder("DROP TABLE IF EXISTS `" + this.tableName + "`;\r\n");
sb.append("CREATE TABLE IF NOT EXISTS `").append(this.tableName).append("`(");
System.out.println("########" + tableName + "########");
String dataType = null;
for (int i = 0; i < columnNamesForSQL.length; i++) {
dataType = columnNameToDbType(this.fieldNames[i]);
if ("VARCHAR".equals(dataType)) {
dataType = dataType + "(" + this.columnLength[i] + ") CHARACTER SET utf8";
}
sb.append(columnNamesForSQL[i]).append(" ").append(dataType).append(",");
}
sb.append("PRIMARY KEY (" + primaryKeyColumnName + ")").append(")ENGINE=InnoDB DEFAULT CHARSET=utf8;");
return sb.toString();
}
/**
* 打印MySQL语句
*/
public void printlnTableCreateSQL() {
System.out.println(generateTableCreateSQL());
}
/**
* 获取实体成员数据类型对应的数据库数据类型
*
* @param fieldName
* @return
*/
private String columnNameToDbType(String fieldName) {
// 主键自增长且不为空
if (primaryKeyFieldName.equals(fieldName)) {
return "BIGINT AUTO_INCREMENT NOT NULL";
}
String r = null;
r = t.get(fieldType.get(fieldName).getName());
return r;
}
}
实体类:
package test.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* 用户表
*
* @author zql
*/
@Table(name="top_zqlweb_user")
@Entity
public class User {
/**
* 主键策略,自增
*/
@Id
@GeneratedValue
@Column(name = "id")
private Long id;
/**
* 用户id
*/
@Column(name = "user_id", length = 64)
private String userId;
/**
* 用户帐号
*/
@Column(name = "account", length = 18)
private String account;
/**
* 密码
*/
@Column(name = "password", length = 72)
private String password;//
/**
* 销户时间
*/
@Column(name = "pin_households_time")
private Long pinHouseholdsTime;
/**
* 是否销户
*/
@Column(name = "pin_households")
private Boolean pinHouseholds;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Long getPinHouseholdsTime() {
return pinHouseholdsTime;
}
public void setPinHouseholdsTime(Long pinHouseholdsTime) {
this.pinHouseholdsTime = pinHouseholdsTime;
}
public Boolean getPinHouseholds() {
return pinHouseholds;
}
public void setPinHouseholds(Boolean pinHouseholds) {
this.pinHouseholds = pinHouseholds;
}
@Override
public String toString() {
return "User [id=" + id + ", userId=" + userId + ", account=" + account + ", password=" + password
+ ", pinHouseholdsTime=" + pinHouseholdsTime + ", pinHouseholds=" + pinHouseholds + "]";
}
}
maven项目依赖:
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
非maven项目需引入以下jar包
javax.persistence-2.0.0.jar
spring-aop-4.3.9.RELEASE.jar
spring-beans-4.3.9.RELEASE.jar
spring-core-4.3.9.RELEASE.jar
commons-logging-1.2.jar