Person的delete请求--------详细过程
首先,数据库的增删改查都是在PersonRepository中实现,因此,直接进入PersonRepository,找到其父类,搜索delete。
@Override @TransactionalMethod public void delete(String id) { Object entity = findEntity(id); deleteEntity(entity); }
protected void deleteEntity(Object entity) { throw new UnsupportedRequestException("Deleting " + ApiUtils.getResourceType(this.getEntityClass()) + " is not supported"); }
sunny之前重写的是delete方法,后面改成重写deleteEntity方法,因为,前者,前面有@TransactionalMethod,故,为了减少对代码的影响,重写deleteEntity方法。
于是,在PersonRepository中,重写方法如下:
@Override public void deleteEntity(Object entity) { Person person = (Person)entity; crmManager.removeParty(person.getId()); }
build代码,发现,并未删除。--------自己debug运行,看代码,检查了很久,都没有找出来原因,因为,明明是调用了removeParty方法,但是,一get请求,被删除的数据还在。
大概郁闷了一天吧,后面,实在没办法,只能找老大帮忙,经过老大的分析,select * from parties where id = 18476,查看数据库,发现,其实数据库并没有真正删除数据,而是将数据的字段isDeleted设置为1,表示该数据已被删除。因此,get请求的时候,这条被删除的数据还是会被查询出来。
也就是sunny总是删除不了的原因。即,所谓的软删除。
因此,再次查看get请求过程,sunny需要重写查询方法。
@Override public D findOne(String id, QuerySpec querySpec) { D dto = findDto(id); this.postFindOne(dto); return dto; } public D findDto(String id) { Object entity = findEntity(id); D dto = createDto(entity); if (!this.getApiContext().isGetHttpMethod()) { updateDtoRelationship(entity, dto); } return dto; }
很明显,这里是通过findEntity(id)方法查询到entity,再通过entity创建dto的。因此,sunny需要重写findEntity方法,让数据库只查询出未被删除的数据。
PersonRepository重写findEntity(id)方法如下:
@Override protected Person findById(String id) { try { Person person = crmManager.findPersonById(Integer.parseInt(id)); if(!person.isDeleted()){ return person; }else { return null; } } catch (PartyNotFoundException e) { throw new ResourceNotFoundException(e.getMessage()); } }
再次build,发现,添加一条数据,然后删除,然后再去swagger中查询这一条数据,发现,真的被删除了,查不到了。
但是,如果是在swagger中查询所有的person,被删除的数据还是能被查询出来。因此,再次,仔细分析findAll的实现过程:
@Override public ResourceList<D> findAll(QuerySpec querySpec) { // Dependent or single instance if (this.getResourceConfiguration().isFindAllDisabled()) { throw new UnsupportedRequestException("Find all " + this.getResourceConfiguration().getResourceType() + " is not allowed."); } QueryParamsHelper helper = getQueryParamsHelper(querySpec); ResourceList<D> resourceList = findAll(helper); postFindAll(resourceList); return resourceList; } public ResourceList<D> findAll(QueryParamsHelper helper) { return query(helper); } @NotNull protected ApiResourceList<D> query(QueryParamsHelper helper) { HibernateQueryOptions hibernateQueryOptions = helper.buildHibernateQueryOptions(this.getEntityClass(), queryService); addInterceptor(hibernateQueryOptions); hibernateQueryOptions.setSelectFetchModeAttribute(this.getResourceConfiguration().getSelectFetchModeAttribute()); QueryResult queryResult = getQueryResult(hibernateQueryOptions); helper.setTotalNumber(queryResult.getTotalNumber()); List<D> resourceList = (List<D>) queryResult.getEntities().stream().map(this::createDto).collect(Collectors.toList()); return new ApiResourceList<>(resourceList, helper); }
sunny意识到,应该要在getEntities的时候,对代码进行重写,也就是,对查询的entity进行条件过滤。但是,对于这行代码
List<D> resourceList = (List<D>) queryResult.getEntities().stream().map(this::createDto).collect(Collectors.toList());
真的是,无从下手,思考了很久,与luke讨论,最后找的simon再次分析,simon建议我去修改hibernate的查询条件,而不需要去重新写一个过滤方法。
于是,新的问题产生了,如何去查看项目的hibernate查询条件呢?----sunny找了很久很久,好无奈,没找到sql语句。
可能是hibernate我不太懂底层原理,总之,花了不少时间查找,就是没找到数据库的sql语句。---------------后期,等老大有时间,sunny再问清楚。
找老大咨询,我应该在哪里修改sql语句,自信查看父类AbstractRepository,最后,老大让我重写getInternalFilters。
public List<FilterComponent> getInternalFilters() { return new ArrayList<>(); }
按住ctrl,再点击getInternalFilters方法名,就可以找到其实现类AbstractHedgeFundProductRepository中实现了该方法:
@Override public List<FilterComponent> getInternalFilters() { List<FilterComponent> filterComponents = new ArrayList<>(); filterComponents.add(new FilterComponent(new FilterFieldDefinition(PRIVATE_EQUITY), FilterOperation.EQUALS, isPrivateEquity())); return filterComponents; }
该方法的功能是,给hibernate动态添加查询条件。模仿其代码,重写personRepository代码如下:
@Override public List<FilterComponent> getInternalFilters() { List<FilterComponent> filterComponents = new ArrayList<>(); filterComponents.add(new FilterComponent(new FilterFieldDefinition(DELETED), FilterOperation.EQUALS, false)); return filterComponents; }
由于数据库的字段名是is_deleted,该方法需要传入与is_deleted相对应的entity的属性名,在
最简单的方法,双击shift,输入deleted,下方会有提示,点击进入ContactMessageSummaryEntity,找到如下代码:
@Column(name = "is_deleted") private boolean deleted;
当然,这里只是为了方便理解,其实真正的查找字段名过程如下:
PersonRepository中:
@Override public void deleteEntity(Object entity) { Person person = (Person)entity; crmManager.removeParty(person.getId()); }
点击removeParty,则
@Override @TransactionalMethod public void removeParty(Integer partyId) { try { Party party = findPartyById(partyId); doDelete(party); } catch (PartyNotFoundException e) { logger.warn("removeParty() called on unknown partyId " + partyId, e); } }
点击doDeleted,则:
private void doDelete(Party party) { if (party.isDeletable()) { LinkUtil.softDeleteLinks(party.getLinks()); party.delete(); updateParty(party); } else { throw new IllegalArgumentException("Party " + party.getId() + " is not deletable; " + party.getReasonNotDeletable()); } }
点击party.delete,则:
@Override public void delete() { setDeleted(true); }
点击setDeleted,则:
@Override public void setDeleted(boolean deleted) throws IllegalStateException { if (deleted) { setDeletedDate(new Date()); contactMessageSummaries = new HashSet<>(); } else { setDeletedDate(null); } this.deleted = deleted; }
注意,这一行代码就是关键:this.deleted = deleted。说明,属性的字段名就是,deleted。点击deleted,则:
private boolean deleted;
因此,下面的代码中,传入的删除字段名为deleted。
感谢luke和我一起找deleted字段。
最后,完整的代码如下:
@Singleton public class PersonRepository extends AbstractRepository<PersonDto> { private static final String DELETED = "deleted"; @Inject protected CrmManager crmManager; protected Person createEntity(PersonDto dto) { //暂时让contactSource定义为null,创建person后再塞值 Person person = crmManager.createPerson(dto.getFirstName(),dto.getLastName(),null); return person; } @Override public void deleteEntity(Object entity) { Person person = (Person)entity; crmManager.removeParty(person.getId()); } @Override protected Person findById(String id) { try { Person person = crmManager.findPersonById(Integer.parseInt(id)); if(!person.isDeleted()){ return person; }else { return null; } } catch (PartyNotFoundException e) { throw new ResourceNotFoundException(e.getMessage()); } } @Override public List<FilterComponent> getInternalFilters() { List<FilterComponent> filterComponents = new ArrayList<>(); filterComponents.add(new FilterComponent(new FilterFieldDefinition(DELETED), FilterOperation.EQUALS, false)); return filterComponents; } }
总结:
1.debug调试要熟练
2.代码运行过程以及原理要清楚,从内部分析,逐条执行,理解,思考后再写代码。
3.写代码的同时,要结合数据库一起查看结果。
4.不懂的要及时问老大,不要浪费过多的时间,因为这个项目太庞大了。
最新文章
- ASP.NET Mvc实用框架(一)Ioc、仓储模式和单元工作模式
- 【GWAS文献】基于GWAS与群体进化分析挖掘大豆相关基因
- myeclipse9中导入的jquery文件报错(出现红叉叉,提示语法错误)
- 用UNIX消息队列实现IPC(以ATM为例)
- (转)Java DES 与Base64
- java 切换
- 多台服务器最好加上相同的machineKey
- 在自己的网站上实现QQ授权登录
- ACM组队安排
- frame嵌套的学习
- Git 和 Github的关系
- Elastarchsearch安装搭建(一)
- android 图片拍照图片旋转的处理方式
- Web安全概述
- mysql Using filesort 索引不可用问题
- Unity3d之-使用BMFont制作美术字体
- http 协议_DNS_域名解析 DNS 服务器_内容分发网络 CDN_缓存机制_HTML5 浏览器存储技术_cookie_sessionStorage_localStorage
- win10操作系统上,wireshark抓取https。
- Python框架学习之用Flask创建一个简单项目
- linux 下安装vscode
热门文章
- LKDBHelper Sqlite操作数据库
- UVA - 242 Stamps and Envelope Size (完全背包+bitset)
- 畅通工程(自己写的BFS,但后面想了下并查集更好更快)
- LeetCode 323. Number of Connected Components in an Undirected Graph
- LeetCode Shopping Offers
- loj 6485 LJJ学二项式定理 —— 单位根反演
- 两种设置WebLogic启动内存的方法
- 利用TaskScheduler处理Queue、Stack等类型的操作队列(生产者消费者场景)
- eclipse -- propedit 安装.
- java中的死锁现象