ORMLite反向重置数据库表

来源:互联网 发布:数据统计用什么软件 编辑:程序博客网 时间:2024/05/22 07:56

如果是Hibernate,反向生成数据库大家肯定会想到hbm2ddl,但是ORMLite呢?ORMLite虽然提供了按照对象来反向生成表的方法,但还不够。因为我希望.新增一个表,不要额外单独写创建表、删除表的操作。

因此想到了Spring的packagesToScan,不过暂未深究Spring,只好找了个现成的类。实现非子目录的扫描:

import java.io.File;import java.io.IOException;import java.lang.annotation.Annotation;import java.net.URL;import java.util.ArrayList;import java.util.Enumeration;import java.util.List;public class ReflectionUtil {private ReflectionUtil() {}public static List<Class<? extends Annotation>> getClassesWithAnnotation(String packageName, Class<? extends Annotation> annotationType) throws ClassNotFoundException, IOException{List<Class<? extends Annotation>> annotatedClassList = new ArrayList<Class<? extends Annotation>>();for(Class type: getClasses(packageName)){if(type.getAnnotation(annotationType) != null){annotatedClassList.add(type);}}return annotatedClassList;}/** * Scans all classes accessible from the context class loader which belong * to the given package and subpackages. *  * @param packageName *            The base package * @return The classes * @throws ClassNotFoundException * @throws IOException */public static List<Class<?>> getClasses(String packageName) throws ClassNotFoundException, IOException{    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();    String path = packageName.replace('.', '/');    Enumeration<URL> resources = classLoader.getResources(path);    List<File> dirs = new ArrayList<File>();    while (resources.hasMoreElements())    {        URL resource = resources.nextElement();        dirs.add(new File(resource.getFile()));    }    List<Class<?>> classes = new ArrayList<Class<?>>();    for (File directory : dirs)    {        classes.addAll(findClasses(directory, packageName));    }    return classes;}/** * Recursive method used to find all classes in a given directory and * subdirs. *  * @param directory *            The base directory * @param packageName *            The package name for classes found inside the base directory * @return The classes * @throws ClassNotFoundException */private static List<Class<?>> findClasses(File directory, String packageName) throws ClassNotFoundException{    List<Class<?>> classes = new ArrayList<Class<?>>();    if (!directory.exists())    {        return classes;    }    File[] files = directory.listFiles();    for (File file : files)    {        if (file.isDirectory())        {            classes.addAll(findClasses(file, packageName + "." + file.getName()));        }        else if (file.getName().endsWith(".class"))        {            classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));        }    }    return classes;}}

完成后就可以在Spring的InitializingBean去干初始化系统的活了,调用ORMLite的数据库操作功能,先drop,后create:

            for(Class<? extends Annotation> type: ReflectionUtil.getClassesWithAnnotation("org.我的包.com", DatabaseTable.class)){                TableUtils.dropTable(connectionSource, type, true);                TableUtils.createTable(connectionSource, type);            }

这里提醒下,大家Spring一般用的是DataSource,而ORMLite用的是ConnectionSource,在ConnectionSource构造方法里有包装DataSource的方法,在spring里配置下即可:

<bean id="connectionSource" class="com.j256.ormlite.jdbc.DataSourceConnectionSource" init-method="initialize"><property name="dataSource" ref="dataSource" /><property name="databaseUrl" value="${dataSource.driverUrl}" /></bean>



不知道如何采用spring package-scan机制完成,看看spring源码理论上应该是可行的。暂未深究,在此就算抛砖引玉了。

/* -------------------- 2016年的分割线 -------------------------- */

之前看过包扫描的代码,自己居然给忘了,这记性……

用包扫描来代替ReflectionUtil,写起来其实非常简单:

for(Class<? extends Annotation> type: ReflectionUtil.getClassesWithAnnotation("org.我的包.com", DatabaseTable.class)){

可以直接换成:

for(Class<? extends Annotation> type: scanOrmLiteClasses("classpath:org/我的包/com/*/xxxx/*.class")){

还支持部分路径匹配,方便极了。scanOrmLiteClasses的代码如下:

    @SuppressWarnings({ "unchecked", "rawtypes" })private List<Class<? extends Annotation>> scanOrmLiteClasses(String pattern) throws URISyntaxException, IOException, ClassNotFoundException{    List<Class<? extends Annotation>> annotatedClassList = new ArrayList<Class<? extends Annotation>>();    int pathLen = Thread.currentThread().getContextClassLoader().getResource(".").toURI().toString().length();    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();    for(Resource resources: resolver.getResources(pattern)){    String uriStr = resources.getURI().toString();    Class scanClass = Class.forName(uriStr.substring(pathLen, uriStr.length() - 6).replaceAll("/", "."));if(scanClass.getAnnotation(DatabaseTable.class) != null){annotatedClassList.add(scanClass);}    }    return annotatedClassList;    }


0 0