侧边栏壁纸
博主头像
小白博主等级

just do it!

  • 累计撰写 60 篇文章
  • 累计创建 77 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

自动生成代码-根据实体类自动生成JPA框架中对应repository、service文件

小白
2020-04-16 / 0 评论 / 0 点赞 / 176 阅读 / 1,377 字

介绍

后端项目开发过程中,对于一些实体映射数据库表的操作经常会写一些重复行代码。本文介绍使用Velocity模板引擎根据实体对象生成JPA框架下对应的Repository类以及Service类,减少一些重复的板砖工作。

可根据具体项目情况添加修改模板文件生成对应代码.

pom.xml文件引入依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--hutool-->
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.1.2</version>
</dependency>
<!--模板引擎-->
<dependency>
	<groupId>org.apache.velocity</groupId>
	<artifactId>velocity-engine-core</artifactId>
	<version>2.0</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
	<scope>runtime</scope>
	<optional>true</optional>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

引入springboot、jpa以及velocity相关依赖

generateCode.properties配置文件

OutputDirRepository=D:\\WorkCoding\\AnTech\\src\\main\\java\\com\\antech\\repository
OutputDirService=D:\\WorkCoding\\AnTech\\src\\main\\java\\com\\antech\\service
entityPackege=com.antech.entity
repositoryPackege=com.antech.repository
servicePackege=com.antech.service

velocity模板文件

repository.java.vm

package ${packagePath};

import com.antech.entity.${entity};
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ${entity}Repository extends JpaRepository<${entity},${idType}> {

}

service.java.vm

package ${packagePath};

import com.antech.repository.${entity}Repository;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

@Service
@Log4j2
public class ${entity}Service {

    @Autowired
    private ${entity}Repository ${lowerEntity}Repository;
}

GenerateCode.java生成代码工具类

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.*;


/**
 * 读取properties/generateCode.properties中的entityPackege包路径下的所有实体对象生成对应mapper/service类
 */
@Log4j2
public class GenerateCode {
    public static void main(String[] args) throws IOException {
        ResourceBundle rb = ResourceBundle.getBundle("properties/generateCode");
        Set<Class<?>> classList = ClassUtil.scanPackage(rb.getString("entityPackege"));
        Set<Class<?>> repositoryClassList = ClassUtil.scanPackage(rb.getString("repositoryPackege"));
        Set<Class<?>> serviceClassList = ClassUtil.scanPackage(rb.getString("servicePackege"));
        Map<String,Boolean> repositoryMap = new HashMap<>();
        Map<String,Boolean> serviceMap = new HashMap<>();
        for(Class clazz : repositoryClassList){
            String[] arr = clazz.getName().split("\\.");
            if(arr.length>0) repositoryMap.put(arr[arr.length-1],true);
        }
        for(Class clazz : serviceClassList){
            String[] arr = clazz.getName().split("\\.");
            if(arr.length>0) serviceMap.put(arr[arr.length-1],true);
        }
        for(Class clazz : classList){
            String[] nameArr =clazz.getName().split("\\.");
            String name = nameArr[nameArr.length-1];
            Map<String, Field> fieldMap = ReflectUtil.getFieldMap(clazz);
            Set<String> set=fieldMap.keySet();
            Field field = null;
            for(String key :set){
                Field field1 = fieldMap.get(key);
                if(field1.isAnnotationPresent(javax.persistence.Id.class)){
                    field=field1;
                    break;
                }
            }
            String[] fieldNameArr=field.getType().getName().split("\\.");
            String idType = fieldNameArr[fieldNameArr.length-1];
            if(!repositoryMap.containsKey(name+"Repository")) generateRepository(rb,new VelocityEngine(),name,idType);
            if(!serviceMap.containsKey(name+"Service")) generateService(rb,new VelocityEngine(),name);
        }
    }

    /**
     *  生成Repository类
     */
    public static boolean generateRepository(ResourceBundle properties,VelocityEngine ve,String entity,String idType) {
        try{
            ve.setProperty(org.apache.velocity.runtime.RuntimeConstants.RESOURCE_LOADER, "classpath");
            ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
            ve.init();// 初始化
            Template template = ve.getTemplate("templates/repository.java.vm");//导入模板
            VelocityContext ctx = new VelocityContext();
            ctx.put("packagePath", "com.antech.repository");
            ctx.put("entity", entity);
            ctx.put("idType", idType);
            StringWriter sw = new StringWriter();
            template.merge(ctx, sw);
            String r = sw.toString();
            File file = new File(properties.getString("OutputDirRepository")+"/"+entity+"Repository.java");
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.append(r);
            fileWriter.flush();
            fileWriter.close();
            log.info(entity+"Repository.java生成成功");
            return true;
        }catch (Exception e){
            log.error(entity+"Repository.java生成失败",e);
            return false;
        }
    }

    /**
     *  生成Service类
     */
    public static boolean generateService(ResourceBundle properties,VelocityEngine ve,String entity) {
        try{
            ve.setProperty(org.apache.velocity.runtime.RuntimeConstants.RESOURCE_LOADER, "classpath");
            ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
            ve.init();// 初始化
            Template template = ve.getTemplate("templates/service.java.vm");//导入模板
            VelocityContext ctx = new VelocityContext();
            String lowerName=StrUtil.lowerFirst(entity);
            ctx.put("packagePath", "com.antech.service");
            ctx.put("entity", entity);
            ctx.put("lowerEntity", lowerName);
            StringWriter sw = new StringWriter();
            template.merge(ctx, sw);
            String r = sw.toString();
            File file = new File(properties.getString("OutputDirService")+"/"+entity+"Service.java");
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.append(r);
            fileWriter.flush();
            fileWriter.close();
            log.info(entity+"Service.java生成成功");
            return true;
        }catch (Exception e){
            log.error(entity+"Service.java生成失败",e);
            return false;
        }
    }
}

使用方式

修改generateCode.properties配置文件中entityPackage值(项目实体类所再的包路径),扫描此包下的实体类生成对应的repository类以及service类,修改repositoryPackage值为需要生成的repository类的目的路径,修改servicePackage值为需要生成的service类的目的路径,修改OutputDirRepository值为需要生成的repository类的文件在计算机中的绝对路径,修改OutputDirService值为需要生成的service类的文件在计算机中的绝对路径。

运行GenerateCode工具类方法,生成实体对应repository文件以及service文件。生成策略:存在即不生成(可根据对应需求修改GenerateCode.java代码,最后的两个if做对那个修改);项目使用了hutool工具类,因此pom文件中hutool依赖必须引入。

附:根据数据库表生成对应JPA实体类请参考以下链接

链接1

0

评论区