java工具类之实体表MySQL建表语句生成类

工具类:

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

发布了55 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/mr_zql/article/details/97181533