页面树结构
转至元数据结尾
转至元数据起始

  本讲开始,进入后端开发培训的内容。

1  DWF的后端架构

  DWF后端层次结构图如下:

  1.Controller层:包含各个Controller类,按照URL将请求分发给相应的函数处理。出于代码复用、层间解耦、异常处理等方面的考虑,Controller层的代码不应包含对业务逻辑的处理,所有与业务逻辑有关的代码应封装到Service层。

  2.Service层:包含业务逻辑的相关类。Service层按照功能内聚的业务模块建模,一个service层的类可使用多个DAO的实体进行持久化操作。

  3.DAO层:DAO 是 Data Access Object(数据访问对象)的缩写,提供对各entity进行增删改查等操作的DAO类。DAO层按照数据对象建模,例如:有Title和Body的领域模型,则对应有TitleDao和BodyDao。

  此外,介绍几个辅助层:

  1.Domain层:包含领域模型,或者说,是JPA维护的Entity,与数据库表一一对应。

  2.Utils类:utils包包含一些常用的工具类,如文件操作、正则表达式处理等。

  下图描述DWF后端标准文件夹的组织形式:

2  与数据库进行交互的RESTful API

  RESTful API主要用来与数据库交互。在DWF,RESTful API与数据库交互有三种方式:

  1.使用DWF内置的OMF(对象管理框架)函数访问实体类、关联类的数据。

  2.使用DWF内置的Hibernate EntityManager直接访问数据库。

  3.使用JDBC或其它方式自行创建连接并维护连接池。

  除非有特殊需求,尽量使用前两种数据库访问方式。

2.1  使用DWF内置的OMF(对象管理框架)函数访问实体类、关联类的数据

  可以注入ObjectAccessService,实现对实体类的查询操作。

@RestController
@RequestMapping("dwf/v1/app-ext")
public class AppExtController {

    @Autowired
    ObjectAccessService objectAccessService;

    @GetMapping(path = "helloworld")
    public ResponseMsg<?> listAllClasses(@RequestParam String name){
        List objs = objectAccessService.getByCondition("Component", "");
        return new ResponseMsg<>(objs);
    }
}

  ObjectAccessService 是DWF的一个由Spring管理的Bean,包含了对DWF管理对象的查询接口:

getByCondition

public List<Map<String,Object>> getByCondition(String className, String condition)

查询对象(不分页)

参数:

className - 实体类名

condition - 查询条件,以and开头。eg: "and plt_oid='43ab314ba35c1345b32a2'"

getByCondition

public List<Map<String,Object>> getByCondition(String className,
                                               String condition,
                                               Integer pageSize,
                                               Integer startIndex,
                                               String sampleMethod)

查询对象(分页)

参数:

className - 实体类名

condition - 查询条件,以and开头。eg:"and plt_oid = '123'"

pageSize - 分页大小,如果不分页可设置为null

startIndex - 分页的起始偏移,如果不分页可设置为null

sampleMethod - 采样方式,如果使用默认顺序采样方式可设置为null

  另外,对对象的增删改操作,可由另外两个Bean完成:ItemClassAccessService 和 RelationAccessService。

  对于实体对象的增删改:ItemClassAccessService:

addEntityObjects

public List<Map<String,Object>> addEntityObjects(String className,
                                                 List<Map<String,Object>> objs)

批量添加实体类对象

参数:

className - 实体类名

objs - 要添加的对象列表。每个对象是一个Map:key是属性名,value是属性值返回:已添加的对象列表

deleteByOids

public void deleteByOids(String className,
                         List<String> oids)

根据oid删除实体类

参数:

className - 实体类名

oids - oid列表

updateEntityObjs

public List<Map<String,Object>> updateEntityObjs(String className,
                                                 List<Map<String,Object>> objs)

批量更新实体类对象。根据对象中的oid确定更新的目标对象

参数:

className - 实体类名

objs - 实体类对象列表

返回:

修改后的对象

cudBatch

public List<Object> cudBatch(List<CudEvent> events)

在一个事务中批量执行多个增、删、改操作

参数:

events - 指定的操作返回:相应的操作结果

public class CudEvent {

public enum ActionType{
create, update, delete
}

/**
* 此操作的类型:增、改、删
*/
ActionType action;

/**
* 此操作所对应的实体类
*/
String className;

/**
* 业务对象集合,在更新对象和创建对象时填写
*/
List<Map<String, Object>> objs;

/**
* 业务对象ID的结合,在删除对象时填写
*/
List<String> oids;

}

addEntityObjectsFast

public List<String> addEntityObjectsFast(String className,
                                         List<Map<String,Object>> objs)

批量快速插入实体类对象。不执行插件,不执行脚本和存储过程,可用于大数据量的导入

参数:

className - 实体类名

objs - 对象列表

返回:

插入对象的oid列表


  对关联类的增删改操作,可由RelationAccessService完成:

addRelations

public List<Map<String,Object>> addRelations(String relName,
                                             List<Map<String,Object>> relObjs)

添加关联对象

参数:

relName - 关联类名

relObjs - 关联对象列表

返回:

添加的关联对象列表

deleteByOids

public void deleteByOids(String relClassName,
                         List<String> oids)

根据Oid删除关联对象

参数:

relClassName - 关联类名

oids - 关联对象OID列表

updateRelations

public List<Map<String,Object>> updateRelations(String relName,
                                                List<Map<String,Object>> relObjs)

更新关联对象。 不允许更新关联的左右连接类(leftClass, rightClass), 左右oid(leftOid, rightOid), rightRev)。如果传入的对象中包含这些属性,这些属性会被自动忽略。

参数:

relName - 关联类名

relObjs - 要更新的关联对象。根据其中的oid决定要更新的对象返回:更新后的对象

getLeftEntityObj

public Map<String,Object> getLeftEntityObj(String relName,
                                           String oid)

获取关联对象的左实体对象

参数:

relName - 关联类名

oid - 关联对象名

返回:

关联对象的左实体对象

getRightEntityObj

public Map<String,Object> getRightEntityObj(String relName,
                                            String oid)

获取关联对象的右实体对象

参数:

relName - 关联类名

oid - 关联对象名

返回:

获取关联对象的右实体对象

2.2  使用DWF内置的Hibernate EntityManager直接访问数据库

  可以在DAO中注入Hibernate框架的EntityManager对象实现增删改查。以下是DAO的程序实例:

@Service
public class AppInfoDao {

    @PersistenceContext
    EntityManager em;

    public List<AppInfoDO> getAll(){
        return em.createQuery("select obj from AppInfoDO obj order by modifyTime desc, appName").getResultList();
    }

    public AppInfoDO getById(String id){
        return em.find(AppInfoDO.class, id);
    }

    public AppInfoDO getByAppName(String appName){
        List<AppInfoDO> list = em.createQuery("select obj from AppInfoDO obj where obj.appName='" + appName + "'", AppInfoDO.class)
                .getResultList();
        if(list.isEmpty()) return null;
        else return list.get(0);
    }

    public void update(AppInfoDO appInfoDO){
        em.merge(appInfoDO);
    }

    @Transactional
    public String add(AppInfoDO appInfoDO){
        appInfoDO.setId(UUIDGenerator.getUUID());
        em.persist(appInfoDO);
        return appInfoDO.getId();
    }

    public void delete(String id){
        AppInfoDO oldAppInfoDO = getById(id);
        if(oldAppInfoDO != null)
            em.remove(oldAppInfoDO);
    }

    public void deleteByName(String appName){
        em.remove(getByAppName(appName));
    }
}

  对Hibernate的介绍,可参考:https://www.baeldung.com/hibernate-entitymanager

  注:Hibernate框架默认的查询语句是HQL。如果需要使用原生SQL,可以使用entityManager.createNativeQuery(..)。


  • 无标签