主要思想:1.自定義註解,標識實體和字段,填寫字段類型、備註等信息 2.實現切面,動態拼接sql,執行更新數據庫(Mybatis/Hibernat/Jdbc)操作。3.添加啓動器,只在項目啓動時執行一次。
功能上 類似於SpringData JPA的自動更新、校驗數據庫
javax.servlet.ServletContextListener
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
logger.info("hibernate.hbm2ddl.auto:"+systemService.getHibernate_hbm2ddl_auto());
if (!"none".equals(systemService.getHibernate_hbm2ddl_auto())) {
long a= DateUtils.getMillis();
SessionFactory sessionFactory = (SessionFactory) webApplicationContext.getBean("sessionFactory");
JdbcTemplate jdbcTemplate = (JdbcTemplate) webApplicationContext.getBean("jdbcTemplate");
Map<String, ClassMetadata> map= sessionFactory.getAllClassMetadata();
logger.info("處理數據庫字段類型長度備註開始,預計耗時 "+map.size()*5236+"ms");
for (int i = 0; i < map.size(); i++) {
System.out.print("-");
}
System.out.println();
for(Entry<String, ClassMetadata> entry:map.entrySet()){
ArrayList<String> arrayList=new ArrayList<String>();
ClassMetadata classMetadata=entry.getValue();
String[] propertyNames= classMetadata.getPropertyNames();
Map<String, String> propertyNameMap=new HashMap<String, String>();
for (String propertyName : propertyNames) {
propertyNameMap.put("get"+propertyName.toLowerCase(), propertyName);
}
propertyNameMap.put("get"+classMetadata.getIdentifierPropertyName().toLowerCase(), classMetadata.getIdentifierPropertyName());
Table table=(Table) classMetadata.getMappedClass().getAnnotation(Table.class);//獲取實體類上的Table 註解
String tableName=table.name();
Comment comment=(Comment) classMetadata.getMappedClass().getAnnotation(Comment.class);//獲取實體類上的Table 註解
Method [] methods= classMetadata.getMappedClass().getMethods();//實體中所有的get方法
//添加表註釋
if (comment!=null) {
arrayList.add(String.format ("EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'%s' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'%s'",comment.value(),tableName));
arrayList.add(String.format ("EXEC sys.sp_updateextendedproperty @name=N'MS_Description', @value=N'%s' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'%s'",comment.value(),tableName));
}
for (Method method : methods) {
Comment commentCol=(Comment) method.getAnnotation(Comment.class);//獲取get方法上的 註解
Column column=(Column) method.getAnnotation(Column.class);//獲取get方法上的 註解
String colName=null;
if (column!=null) {
if (StringUtil.isNotBlank(column.name()) ) {
colName=column.name();
}else {
colName=propertyNameMap.get(method.getName().toLowerCase());
}
}
if (commentCol!=null&&colName!=null) {
arrayList.add( String.format (" EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'%s' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'%s', @level2type=N'COLUMN',@level2name=N'%s'",commentCol.value(),tableName,colName));
arrayList.add( String.format (" EXEC sys.sp_updateextendedproperty @name=N'MS_Description', @value=N'%s' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'%s', @level2type=N'COLUMN',@level2name=N'%s'",commentCol.value(),tableName,colName));
}
if (column!=null&&method.getReturnType().equals(String.class)) {
if (commentCol!=null&&StringUtil.isNotEmpty(commentCol.fieldType())) {//如果定義了字段類型
if (colName.equals(classMetadata.getIdentifierPropertyName())) {//主鍵
StringBuilder sql=new StringBuilder();
sql.append(" DECLARE @s nvarchar(500); ");
sql.append(" SELECT ");
sql.append(" @s = 'alter table ' + b.name + ' drop constraint ' + a.name ");
sql.append(" FROM sysobjects a ");
sql.append(" LEFT JOIN sysobjects b ");
sql.append(" ON a.parent_obj = b.id ");
sql.append(" WHERE a.xtype = 'PK' ");
sql.append(" AND b.name = '"+tableName+"' ; ");
sql.append(" EXEC (@s) ; ");
sql.append(String.format (" alter table %s alter column %s %s not null ;", tableName, colName,commentCol.fieldType() )) ;
sql.append(String.format (" alter table %s add constraint PK_%s primary key( %s );",tableName,tableName,colName));
arrayList.add( sql.toString());
}else {
arrayList.add( String.format (" alter table %s alter column %s %s ", tableName, colName,commentCol.fieldType() ));
}
}else {
if (colName.equals(classMetadata.getIdentifierPropertyName())) {//主鍵
StringBuilder sql=new StringBuilder();
sql.append(" DECLARE @s nvarchar(500); ");
sql.append(" SELECT ");
sql.append(" @s = 'alter table ' + b.name + ' drop constraint ' + a.name ");
sql.append(" FROM sysobjects a ");
sql.append(" LEFT JOIN sysobjects b ");
sql.append(" ON a.parent_obj = b.id ");
sql.append(" WHERE a.xtype = 'PK' ");
sql.append(" AND b.name = '"+tableName+"' ; ");
sql.append(" EXEC (@s) ; ");
sql.append(String.format (" alter table %s alter column %s nvarchar(%d) not null ;", tableName, colName,column.length() )) ;
sql.append(String.format (" alter table %s add constraint PK_%s primary key( %s );",tableName,tableName,colName));
arrayList.add( sql.toString());
}else {
arrayList.add( String.format (" alter table %s alter column %s nvarchar(%d) ", tableName, colName,column.length() ));
}
}
}
}
for (String string : arrayList) {
try {
jdbcTemplate.execute(string);
logger.debug("execSQL{}"+string);
} catch (Exception e) {
// TODO: handle exception
}
}
System.out.print(">");
}
System.out.println();
long b= DateUtils.getMillis();
logger.info("處理數據庫字段類型長度備註結束 耗時:{}"+(b-a)+"ms");
}