SQLserver备份还原系统

本文介绍了一种基于SpringBoot框架的SQLserver备份还原系统的设计与实现。系统支持远程备份还原,自定义功能扩展,并提供了良好的用户界面。文章还详细展示了自定义注解实现自动建表的过程及关键代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SQLserver备份还原系统

概述

为什么需要网站来实现对数据库的备份还原,理由如下:

  • 可以远程备份还原,上传自己本地备份进行还原,方便管理
  • 有些linux电脑安装了SQLserver数据库,还原没有本地客户端支持,只能敲命令
  • 支持编写自定义功能,扩展本地客户端功能。

初步设计

1、程序建表问题,自动创建表格,可以采用自己编写注解的方式进行,类似hibernate注解,启动程序的时候解析bean的注解并进行生成表格。
2、程序界面采用一款好看的主题inspinia_admin进行二次扩展。
3、程序后台架构采用SpringBoot + SpringMVC + Spring + Mybatis
4、程序前台架构除了采用主题,扩展了几个常用插件jquery.form.js【异步提交form】+jquery loading【等待提示】+jquery confirm【确认弹框插件】等常用的前台组件

部分界面截图

#####登录界面
登录界面

#####主界面
主界面

响应式网站所以手机端访问也兼容,下面是移动端浏览器截图

#####移动端登录
移动端登录

#####移动端主界面
移动端主界面

主界面2

部分关键代码

整体架构 :
代码架构

自定义注解实现自动建表,这里以前有详细讲述ssm 自定义注解实现mybatis自动维护表结构以及利用freemarker生成代码
编写自定义注解类

//表示注解加在接口、类、枚举等
@Target(ElementType.TYPE)
//VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息
@Retention(RetentionPolicy.RUNTIME)
//将此注解包含在javadoc中
@Documented
//允许子类继承父类中的注解
@Inherited
public @interface AutoCode {
	/**
	 * 是否可以覆盖原先自动生成的文件
	 * 默认不覆盖已有的文件
	 * @return
	 */
	public abstract boolean isOverride() default false;
	/**
	 * 默认false
	 * 是否包含pojo对象的父类,这里只支持一层继承关系
	 * @return
	 */
	public abstract boolean includeSupperClass() default false;
}
//该注解用于方法声明
@Target(ElementType.FIELD)
//VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息
@Retention(RetentionPolicy.RUNTIME)
//将此注解包含在javadoc中
@Documented
//允许子类继承父类中的注解
@Inherited
public @interface Column {
	/**
	 * 默认当前字段名。
	 * @return
	 */
	public abstract String name() default "";
	/**
	 * 默认值是normal
	 * 仅可以填写【primary,normal】其他无效。
	 * 可以多个字段都是primary做联合主键。
	 * @return
	 */
	public abstract String flag() default "normal";
	/**
	 * 默认值是varchar(50)
	 * 【varchar(50),decimal(18,2),int,smallint,...】
	 * 字段类型,支持SQLSERVER数据库类型
	 * @return
	 */
	public abstract String type() default "varchar(50)";
	
	/**
	 * 字段默认值
	 * 支持 newid()方法
	 * 支持变量如下【@hbdwbh,@dwbh,@year,@month】
	 * @return
	 */
	public abstract String defaultValue() default "";
	/**
	 * 【identity(1,1),NOT NULL,NULL】
	 * 自增,非空,空,默认空值
	 * 默认不写表示primary则是NOT NULL normal是NULL 如果是normal 想要NOT NULL 可以加OTH="NOT NULL"
	 * @return
	 */
	public abstract String oth() default "";
	
	
	//=====================================JS 设定部分===========================================//
	/**
	 * 生成js model时候的数据类型,如果不指定,他会根据type来判断类型
	 * 例如boolean 数据库没有这个类型,而js需要,所以单独出来。但是如果跟数据库一致,则不需要配置
	 * 默认取type()值。
	 * @return
	 */
	public abstract String jstype() default "";
	
	/**
	 * 生成grid 或者tree 的列名称 如果为空则不显示在页面上
	 * @return
	 */
	public abstract String jsname() default "";
	
	/**
	 * 设置列在 js grid 里面的宽度
	 * 默认所有列1:1平均分。
	 * @return
	 */
	public abstract int jswidth() default 0;
	
	
	/**
	 * 是否允许为空
	 * 默认允许为空
	 * @return
	 */
	public abstract boolean jsAllowBlank() default true;
	
	/**
	 * 主页面隐藏该列,但增加修改页面会显示出来。如果都不要这个列显示,只需要把jsname=''即可。
	 * 默认显示(false)
	 * @return
	 */
	public abstract boolean jshidden() default false;
	
	/**
	 * 当其为空则会自动获取jstype来判断,当jstype为空时候会自动获取type进行判断
	 * 这里针对增加修改的展示的 xtype进行定义特殊的组件例如 radioGroup,checkBox等不能用
	 * 数据库字段类型或者jstype类型判断的类型进行定义。
	 * e.g.  radiogroup [部分配置项 例如"items:[{
                        inputValue: 'visa',
                        name : 'xxx',
                        boxLabel: 'VISA',
                        checked: true
                    }, {
                        inputValue: 'mastercard',
                        name : 'xxx',
                        boxLabel: 'MasterCard'
                    }]]
	 * @return
	 */
	public abstract String jsxtype() default "";
	
	//=================================tree ============================//
	/**
	 * 如果是树的话需要指定主列
	 * @return
	 */
	public abstract boolean treecolumn() default false;
	/**
	 * 标识该属性为tree id
	 * 与treeparentid对应
	 * @return
	 */
	public abstract boolean treeId() default false;
	/**
	 * 标识树父节点是哪个字段
	 * @return
	 */
	public abstract boolean treeparentId() default false;
	/**
	 * 要求数据库类型和属性类型必须为int。
	 * @return
	 */
	public abstract boolean treeleaf() default false;
	
	/**
	 * 对树起作用,会自动汇总子节点的数值在增删改子节点的时候。
	 * @return
	 */
	public abstract boolean treeSum() default false;
	/**
	 * e.g.  function(value,cellmeta,record,row,col,store){if(value=='1'){return '支出类型'}else {return '收入类型'}}
	 * 与extjs renderer 编写的方法内容一致。采取直接替换。
	 * @return
	 */
	public abstract String render() default "";
	/**
	 * e.g.  where hbdwbh = ? and dwbh = ? and keyid = value 
	 * 只过滤 hbdwbh,dwbh,以及设定的当前列。
	 * 对于不分年的表,若要对里面的年份也进行过滤,需要自己修改代码。
	 * @return
	 */
	public abstract boolean jsValidator() default false;
	/**
	 * e.g.  1  101  10101  102 10201 
	 * 自动根据数据库记录按上方规则生成主键代码。
	 * 只能放置于 treeId 是true 的列
	 * @return
	 */
	public abstract boolean autoGenneral() default false;
	
}

我们只要在bean里写上注解即可。

@Table(name = "SIQ_DatabaseBackupVersion")
public class DBBackupInfoBean implements Serializable {
    /**
     * UID
     */
    private static final long serialVersionUID = -8313977153833723277L;
    @Column
    private String dvid;
    @Column(type="varchar(500)")
    private String dvname;
    @Column
    private String dvtime;
    @Column
    private String addUser;
    @Column(type="varchar(500)")
    private String dvinfo;
    @Column(type="varchar(500)")
    private String dvpath;
    @Column
    private String dbname;
    @Column(type = "int")
    private int autobackup;
    /**
     * Getters & Setters
     *
     * @return
     */
}

解析类如下:

/**
 * 自动扫描pojo包下的实体类,进行注解解析生成表结构语句并维护表结构
 * @author chenfuqiang
 *
 */
@Service("autoFixTable")
@Transactional
public class AutoFixTableSQLServerImpl implements AutoFixTable{
	/**
	 * 要扫描的model所在的pack
	 */
	private String pack = Global.PACKAGEOFPOJO;
	@Resource
	private CommonDao commonDao;
	
	@Override
	public StateInfo run(int year) {
		long begin = System.currentTimeMillis();
		Logger.getLogger(this.getClass()).info("---开始自动修复表结构---");
		Set<Class<?>> classes = ClassTools.getClasses(pack);
		StateInfo stateInfo = dealClassSQL(classes,year);
		long end = System.currentTimeMillis();
		Logger.getLogger(this.getClass()).info("---结束自动修复表结构---");
		Logger.getLogger(this.getClass()).info("总共花费了"+((end-begin)*0.001)+"秒");
		return stateInfo;
	}
	
	public StateInfo dealClassSQL(Set<Class<?>> classes,int year) {
		StateInfo stateInfo = new StateInfo();
		List<String> sqlAdd = new ArrayList<String>();
		List<String> sqlUpt = new ArrayList<String>();
		List<String> sqlPK = new ArrayList<String>();
 		List<String> sqlEtc = new ArrayList<String>();
		Map<String,String> table_indexName = this.getKeyName();
		StringBuffer keyBuf = new StringBuffer();
		StringBuffer keyEditBuf = new StringBuffer();
		StringBuffer allBuf = new StringBuffer();
		StringBuffer addBuf = new StringBuffer();
		StringBuffer editBuf = new StringBuffer();
		StringBuffer pkBuf = new StringBuffer();
		StringBuffer dvBuf = new StringBuffer();

		if(year == 0 ) {
			year = Integer.parseInt(new SimpleDateFormat("yyyy").format(new Date()));
		}
		
		for (Class<?> clas : classes){
			addBuf.setLength(0);
			keyBuf.setLength(0);
			keyEditBuf.setLength(0);
			pkBuf.setLength(0);
			editBuf.setLength(0);
			dvBuf.setLength(0);
			allBuf.setLength(0);
			
			Table table = clas.getAnnotation(Table.class);
			if(table == null) {
				continue;
			}
			String tablename = table.name();
			if(CommonUtil.isEmpty(tablename)) {
				tablename = clas.getSimpleName();
			}
			tablename = tablename.toUpperCase().replace("@YEAR", String.valueOf(year));
			//==================================================================================//
			//去掉索引,然后再修改列
			String indexName = table_indexName.get(tablename.toUpperCase());
			if(!CommonUtil.isEmpty(indexName)){
				pkBuf.append("ALTER TABLE "+tablename+" drop CONSTRAINT "+indexName+" \r\n");
				sqlPK.add(pkBuf.toString());
			}
			addBuf.append("CREATE TABLE [dbo].[").append(tablename).append("]( \r\n");
			
			Field[] fields = clas.getDeclaredFields();

// 			这里支持集成的父类,要支持只要把下面的fields 附加到子类的fields即可。
			if(table.includeSupperClass()) {
				if(clas.getSuperclass()!=null){
					Class<?> clsSup = clas.getSuperclass();
					fields = (Field[]) ArrayUtils.addAll(fields,clsSup.getDeclaredFields());
				}
			}
			for (Field field : fields){
				Column column = field.getAnnotation(Column.class);
				if(column == null) {continue;}
				String columnname = CommonUtil.isEmpty(column.name())?field.getName():column.name();
				String flag = column.flag();
				String dv = column.defaultValue();
				String oth = column.oth();//identity(1,1)
				if(!CommonUtil.isEmpty(dv)) {
					dv = dv.toUpperCase().replace("@YEAR", String.valueOf(year));
				}
				String type = column.type();
				
				addBuf.append("[").append(columnname).append("] ").append(type).append(" ");
				if(!CommonUtil.isEmpty(oth)) {
					addBuf.append(" "+oth+" ");
				}
				if("PRIMARY".equals(CommonUtil.nullToStr(flag).toUpperCase())) {
					keyBuf.append("[").append(columnname).append("] ASC,\r\n");
					keyEditBuf.append(columnname).append(",");
					
					addBuf.append(" NOT NULL ");
				}
				if(!CommonUtil.isEmpty(dv)) {
					addBuf.append(" DEFAULT (").append(dv).append(") ");
					dvBuf.append("Update ").append(tablename).append(" Set ").append(columnname).append("=").append(dv).append(" ");
					dvBuf.append("Where ").append(columnname).append(" is null").append(" \r\n");
				}
				addBuf.append(",\r\n");
				//===================================UPDATE FIELDS=================================//
				editBuf.append("IF EXISTS(SELECT * FROM syscolumns WHERE ID=OBJECT_ID('"+tablename+"') AND NAME='"+columnname+"') \r\n");
				editBuf.append("BEGIN \r\n");
				editBuf.append("ALTER TABLE ").append(tablename).append(" ALTER column ").append(columnname).append(" ").append(type).append(" ");
				if("PRIMARY".equals(CommonUtil.nullToStr(flag).toUpperCase())) {
					editBuf.append(" NOT NULL ");
				}else {
					if(!CommonUtil.isEmpty(oth)) {
						editBuf.append(" NOT NULL ");
					}
				}
				editBuf.append(" \r\n");
				editBuf.append("END \r\n");
				editBuf.append("IF NOT EXISTS(SELECT * FROM syscolumns WHERE ID=OBJECT_ID('"+tablename+"') AND NAME='"+columnname+"') \r\n");
				editBuf.append("BEGIN \r\n");
				editBuf.append("ALTER TABLE ").append(tablename).append(" add ").append(columnname).append(" ").append(type).append(" ");
				if("PRIMARY".equals(CommonUtil.nullToStr(flag).toUpperCase())) {
					editBuf.append(" NOT NULL ");
				}else {
					if(!CommonUtil.isEmpty(oth)) {
						editBuf.append(" NOT NULL ");
					}
				}
				editBuf.append(" \r\n");
				editBuf.append("END \r\n");
			}
			if(keyBuf.length() != 0) {
				addBuf.append("CONSTRAINT [PK_" + tablename+ "] PRIMARY KEY CLUSTERED ( \r\n");
				addBuf.append(keyBuf.substring(0,keyBuf.length()-3));
				addBuf.append(") ON [PRIMARY] \r\n");
			}else {
				addBuf.delete(addBuf.length()-3, addBuf.length()-1);
			}
				addBuf.append(") ON [PRIMARY] \r\n");
			allBuf.append("IF EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID(N'[dbo].["+ tablename+ "]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) \r\n");
			allBuf.append("BEGIN \r\n");
			allBuf.append(editBuf.toString());
			allBuf.append("END \r\n");
			sqlUpt.add(allBuf.toString());
			
			allBuf.append("IF NOT EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID(N'[dbo].["+ tablename+ "]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) \r\n");
			allBuf.append("BEGIN \r\n");
			allBuf.append(addBuf.toString());
			allBuf.append("END \r\n");
			sqlAdd.add(allBuf.toString());
			
			//修改主键需要在列都修改完执行完之后再修改主键,因为有些列是NULL,修改完列后就是NOT NULL
			//=====================================UPDATE TABLE ===============================//
			//修改默认值
			if(dvBuf.length() != 0) {
				sqlEtc.add(dvBuf.toString());
			}
			//修改主键
			if(keyBuf.length() != 0) {
				allBuf.setLength(0);
				allBuf.append("IF EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID(N'[dbo].["+ tablename+ "]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) \r\n");
				allBuf.append("BEGIN \r\n");
				allBuf.append("alter table "+tablename+" add constraint pk_"+tablename+" primary key ("+keyEditBuf.substring(0,keyEditBuf.length()-1)+") \r\n");
				allBuf.append("END \r\n");
				sqlEtc.add(allBuf.toString());
			}
		}
		//======================================JDBC===============================================//
		try {
			
			if(sqlAdd.size()>0) {
				commonDao.transactionUpdate(sqlAdd);
				Logger.getLogger(this.getClass()).info("--新增数据库表完成--");
			}
			if(sqlUpt.size()>0) {
				commonDao.transactionUpdate(sqlUpt);
				Logger.getLogger(this.getClass()).info("--修改数据库表完成--");
			}
			if(sqlPK.size()>0) {
				commonDao.transactionUpdate(sqlPK);
				Logger.getLogger(this.getClass()).info("--主键删除完成--");
			}
			if(sqlEtc.size()>0) {
				commonDao.transactionUpdate(sqlEtc);
				Logger.getLogger(this.getClass()).info("--其他操作完成--");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			Logger.getLogger(this.getClass()).error(e.getMessage());
			stateInfo.setFlag(false);
			stateInfo.setMsg(this.getClass(),e.getMessage());
		}
		return stateInfo;
	}

	
	public Map<String,String> getKeyName() {
//		select a.name,b.name from sysobjects a left join sysobjects b on a.parent_obj = b.id where 1=1 
//		and a.xtype='pk'
		StringBuffer sqlBuffer = new StringBuffer();
		sqlBuffer.append("select b.name AS [表名], ");
		sqlBuffer.append("a.name  AS [主键名称] ");
		sqlBuffer.append("from  dbo.sysobjects a left join  dbo.sysobjects b on a.parent_obj = b.id where 1=1 ");
		sqlBuffer.append("and a.xtype='pk' ");
		List<Map<String,Object>> list = commonDao.getListForMap(sqlBuffer.toString());
		Map<String,String> result = new HashMap<String, String>();
		for(Map<String,Object> m : list) {
			result.put(String.valueOf(m.get("表名")).toUpperCase(), String.valueOf(m.get("主键名称")));
		}
		return result;
	}
	
}

备份还原关键代码:
新增备份文件:

@Override
    public StateInfo addDBInfo(User user, DBBackupInfoBean backupInfoBean,String Flag) {
        StateInfo stateInfo = new StateInfo();
        try {
            Date date = new Date();
            backupInfoBean.setAddUser(user.getUsername());
            backupInfoBean.setAutobackup(0);
            backupInfoBean.setDvtime(Global.df.format(date));

            StringBuffer sqlTemp = new StringBuffer();
            /**
             * 备份数据库SQL语句
             */
            List<String> sqlList = new ArrayList<String>();
            if(Flag == null) {
                String path = System.getProperty("user.dir")+"/backupfile";
                File file = new File(path);
                if (file.exists() == false) {
                    file.mkdirs();
                }
                backupInfoBean.setDvpath(path+"/"+backupInfoBean.getDvname()+Global.dfpath.format(date)+".SiQ");
                Logger.getLogger(this.getClass()).info("备份文件路径:"+backupInfoBean.getDvpath());
                sqlTemp.append("backup database " + backupInfoBean.getDbname()+ " to disk='" + backupInfoBean.getDvpath() + "' with init");
                sqlList.add(sqlTemp.toString());
            }
            sqlTemp.setLength(0);
            sqlTemp.append("Insert into SIQ_DatabaseBackupVersion(dvid,dvname,dvtime,addUser,dvinfo,dvpath,dbname,autobackup) values (");
            sqlTemp.append("newid(),'").append(CommonUtil.isEmpty(backupInfoBean.getDvname())?backupInfoBean.getDbname().toUpperCase():backupInfoBean.getDvname()).append("',");
            sqlTemp.append("'").append(backupInfoBean.getDvtime()).append("',");
            sqlTemp.append("'").append(backupInfoBean.getAddUser()).append("',");
            sqlTemp.append("'").append(CommonUtil.isEmpty(backupInfoBean.getDvinfo())?"用户没有填写":backupInfoBean.getDvinfo()).append("',");
            sqlTemp.append("'").append(backupInfoBean.getDvpath()).append("',");
            sqlTemp.append("'").append(backupInfoBean.getDbname()).append("',");
            sqlTemp.append(backupInfoBean.getAutobackup());
            sqlTemp.append(")");
            sqlList.add(sqlTemp.toString());
            sqlTemp.setLength(0);
            dao.transactionUpdate(sqlList);
        }catch (Exception e) {
            stateInfo.setFlag(false);
            stateInfo.setMsg(this.getClass(),e.getMessage());
        }
        return stateInfo;
    }

还原备份文件

@Override
    public StateInfo restore(String dbname, String vid) {
        StateInfo stateInfo = new StateInfo();
        try {
            Map<String,Object> dvInfo = this.getBackupInfo(vid);
            String filePath = String.valueOf(dvInfo.get("dvpath"));
            File backupFile = new File(filePath);
            /**
             * 判断文件是否存在,不存在则给予提示。
             * 不存在可能由于误删了备份文件夹backupfile里面的文件。
             */
            if (backupFile.exists()) {
                StringBuilder sqlBuffer = new StringBuilder();
                try{
                    sqlBuffer.append("create proc p_killspid ");
                    sqlBuffer.append("@dbname sysname ");
                    sqlBuffer.append("as  ");
                    sqlBuffer.append("declare @s nvarchar(1000) ");
                    sqlBuffer.append("declare tb cursor local for ");
                    sqlBuffer.append("select s='kill '+cast(spid as varchar) ");
                    sqlBuffer.append("from master..sysprocesses  ");
                    sqlBuffer.append("where dbid=db_id(@dbname) ");
                    sqlBuffer.append("open tb ");
                    sqlBuffer.append("fetch next from tb into @s ");
                    sqlBuffer.append("while @@fetch_status=0 ");
                    sqlBuffer.append("begin ");
                    sqlBuffer.append("exec(@s) ");
                    sqlBuffer.append("fetch next from tb into @s ");
                    sqlBuffer.append("end ");
                    sqlBuffer.append("close tb ");
                    sqlBuffer.append("deallocate tb ");
                    dao.executeSQL(sqlBuffer.toString());
                } catch (Exception e) {
                    //不需要捕获,第二次创建会报错,无所谓这边。
                }
                sqlBuffer.setLength(0);
                /**
                 * 获取当前被还原的备份文件路径
                 */
                sqlBuffer.append("RESTORE FILELISTONLY FROM DISK = N'" + filePath + "'");
                List<Map<String,Object>> tempInfos = dao.getListForMap(sqlBuffer.toString());
                if(CommonUtil.isNotEmptyList(tempInfos)&&tempInfos.size()>1) {
                    /**
                     * 备份文件里面存的mdf ldf存在的路径
                     */
                    String olddb = String.valueOf(tempInfos.get(0).get("LogicalName"));
                    String olddb_log = String.valueOf(tempInfos.get(1).get("LogicalName"));
                    /**
                     * 关闭被还原数据库的所有连接
                     * 让所有连接到这个库的连接都断掉,不然无法还原数据库会提示被占用。
                     */
                    dao.executeSQL("exec p_killspid  '" + dbname + "'");
                    /**
                     * 还原后的数据库mdf ldf存放的路径
                     */
                    String path = System.getProperty("user.dir")+"/MSSQL_DATA/";
                    File file = new File(path); if (file.exists() == false) {file.mkdirs();}
                    /**
                     * 开始还原操作
                     */
                    sqlBuffer.setLength(0);
                    sqlBuffer.append("RESTORE DATABASE " + dbname + " FROM DISK = '" + filePath + "' ");
                    sqlBuffer.append("WITH REPLACE,MOVE '" + olddb + "' TO '"
                            + path + dbname + ".mdf', MOVE '" + olddb_log + "' TO '"
                            + path + dbname + "_log.ldf'");
                    dao.executeSQL(sqlBuffer.toString());
                }else {
                    stateInfo.setFlag(false);
                    stateInfo.setMsg(this.getClass(),"读取备份文件内部还原信息失败!SQL:"+sqlBuffer.toString());
                }
            }else {
                stateInfo.setFlag(false);
                stateInfo.setMsg(this.getClass(),"备份文件丢失,此记录已经失效!路径:"+filePath);
            }
        }catch (Exception e) {
            stateInfo.setFlag(false);
            stateInfo.setMsg(this.getClass(),e.getMessage());
        }
        return stateInfo;
    }

接触过sqlserver的都知道他有mdf和ldf两个文件,ldf主要记录日志,那么有时候我们并不需要通过日志来恢复数据,需要删除他来节约硬盘空间,这里可以通过语句来实现:

@Override
    public StateInfo clearDBLog(String dbname) {
        StateInfo stateInfo = new StateInfo();
        try {
            StringBuffer sqlBuffer = new StringBuffer();
            sqlBuffer.append("select name from "+dbname+".dbo.sysfiles where fileid = '2'");
            List<Map<String,Object>> maps = dao.getListForMap(sqlBuffer.toString());
            if(maps.size()>0) {
                String tempDBLOG = String.valueOf(maps.get(0).get("name"));
                List<String> sqls = new ArrayList<String>();
                sqlBuffer.setLength(0);
                sqlBuffer.append("alter database "+dbname+" set recovery simple");
                sqls.add(sqlBuffer.toString());

                sqlBuffer.setLength(0);
                sqlBuffer.append("dbcc shrinkfile ("+tempDBLOG+",1)");
                sqls.add(sqlBuffer.toString());

                /**
                 * 恢复完全模式,会详细记录日子。
                 */
//                sqlBuffer.setLength(0);
//                sqlBuffer.append("alter database "+dbname+" set recovery full");
//                sqls.add(sqlBuffer.toString());
                dao.transactionUpdate(sqls);
            }else {
                stateInfo.setFlag(false);
                stateInfo.setMsg(this.getClass(),"执行语句未得到结果:"+sqlBuffer.toString());
            }
        }catch (Exception e) {
            stateInfo.setFlag(false);
            stateInfo.setMsg(this.getClass(),e.getMessage());
        }
        return stateInfo;
    }

##码云代码
Github地址:kkillala/mssql-web
码云地址: Tim / mssql-web
喜欢的话欢迎订阅关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆呆的小青蛙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值