美文网首页
JPA 双向映射反复查询解决办法

JPA 双向映射反复查询解决办法

作者: 圣光会制裁你丨 | 来源:发表于2017-07-12 16:55 被阅读94次
    EntitlementTransaction的结构:
    @Entity
    @Table(name = EntitlementTransactionConstant.TABLE_ENTITLEMENT_TRANSACTION)
    public class EntitlementTransaction implements Serializable {
     
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(generator = "system-uuid")
    @Column(name = EntitlementTransactionConstant.GUID )
    private String guid;
    
    @Column(name = EntitlementTransactionConstant.TRANSACTIONID,nullable = false)
    private String transactionID;
    
    @Column(name = EntitlementTransactionConstant.ENTITLEMENTNAME)
    private String entitlementName;
    
    @Column(name = EntitlementTransactionConstant.TYPE)
    private String type;
    
    @Column(name = EntitlementTransactionConstant.TENANTID)
    private long tenantID;
    
    @Column(name = EntitlementTransactionConstant.CUSTOMER)
    private String customer;
    
    @Column(name = EntitlementTransactionConstant.STORAGE)
    private long storage;
    
    @Column(name = EntitlementTransactionConstant.CPUCORE)
    private long cpuCore;
    
    @Column(name = EntitlementTransactionConstant.USERCOUNT)
    private long userCount;
    
    @Column(name = EntitlementTransactionConstant.STATUS)
    private String status;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = EntitlementTransactionConstant.ENTITLEMENTID)
    private EntitlementMaster entitlementMaster ;
    
    
    @Entity
    @Table(name = EntitlementMasterConstant.TABLE_Master_Constant)
    public class EntitlementMaster implements Serializable {
    
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(generator = "system-uuid")
    @Column(name = EntitlementMasterConstant.GUID)
    private String guid;
    
    @Column(name = EntitlementMasterConstant.ENTITLEMENTNAME)
    private String entitlementName;
    
    @Column(name = EntitlementMasterConstant.ENTITLEMENTGUID)
    private String entitlementID;
    
    @Column(name = EntitlementMasterConstant.TYPE)
    private String type;
    
    @Column(name = EntitlementMasterConstant.TENANTID)
    private long tenantID;
    
    @Column(name = EntitlementMasterConstant.CUSTOMER)
    private String customer;
    
    @Column(name = EntitlementMasterConstant.STORAGE)
    private long storage;
    
    @Column(name = EntitlementMasterConstant.CPUCORE)
    private long cpuCore;
    
    @Column(name = EntitlementMasterConstant.USERCOUNT)
    private long userCount;
    
    @Column(name = EntitlementMasterConstant.OPERANT)
    private String Operant;
    
    @OneToMany(mappedBy = "entitlementMaster", fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    private Set<EntitlementTransaction> entitlementTransaction = new HashSet<>();
    
    EntitleMaster的结构:
    @Entity
    @Table(name = EntitlementMasterConstant.TABLE_Master_Constant)
    public class EntitlementMaster implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(generator = "system-uuid")
    @Column(name = EntitlementMasterConstant.GUID)
    private String guid;
    
    @Column(name = EntitlementMasterConstant.ENTITLEMENTNAME)
    private String entitlementName;
    
    @Column(name = EntitlementMasterConstant.ENTITLEMENTGUID)
    private String entitlementID;
    
    @Column(name = EntitlementMasterConstant.TYPE)
    private String type;
    
    @Column(name = EntitlementMasterConstant.TENANTID)
    private long tenantID;
    
    @Column(name = EntitlementMasterConstant.CUSTOMER)
    private String customer;
    
    @Column(name = EntitlementMasterConstant.STORAGE)
    private long storage;
    
    @Column(name = EntitlementMasterConstant.CPUCORE)
    private long cpuCore;
    
    @Column(name = EntitlementMasterConstant.USERCOUNT)
    private long userCount;
    
    @Column(name = EntitlementMasterConstant.OPERANT)
    private String Operant;
    
    @OneToMany(mappedBy = "entitlementMaster", fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    private Set<EntitlementTransaction> entitlementTransaction = new HashSet<>();
    

    这两张表通过EntitlementID字段来维持了双向映射的关系,在通过JPA对EntitlementTransaction表进行findALL()操作时,会因为这种双向映射关系导致反复查询同一条数据的情况,先来看数据库中的数据:

    数据库中的数据

    而查询出来的数据却是这样的:

    查询出的数据

    这个时候的Service层的代码是这样的:

    @Autowired
    EntitlementTransactionRepository entitlementTransactionRepository;
    @Override
    public List<EntitlementTransaction> getAll(){
        return  entitlementTransactionRepository.findAll();
    }
    

    如何解决这个问题呢?
    首先新建EntitlementTransactionDtoNew类:

    public class EntitlementTransactionDtoNew
    {
    private String guid;
    private String entitlementID;
    private String transactionID;
    private String entitlementName;
    private String type;
    private long tenantID;
    private String customer;
    private long storage;
    private long cpuCore;
    private long userCount;
    private String status;
    
    getter and setter......
    }
    

    改写Service中的查询代码:

    @Override
    public List<EntitlementTransactionDtoNew> getAll(){
        List<EntitlementTransactionDtoNew> entitlementTransactionDtoNews = new ArrayList<>();
        for(EntitlementTransaction entitlementTransaction : entitlementTransactionRepository.findAll()){
            EntitlementTransactionDtoNew entitlementTransactionDto = new EntitlementTransactionDtoNew();
            entitlementTransactionDto.setGuid(entitlementTransaction.getGuid());
            entitlementTransactionDto.setEntitlementID(entitlementTransaction.getEntitlementMaster().getEntitlementID());
            entitlementTransactionDto.setTransactionID(entitlementTransaction.getTransactionID());
            entitlementTransactionDto.setEntitlementName(entitlementTransaction.getEntitlementName());
            entitlementTransactionDto.setType(entitlementTransaction.getType());
            entitlementTransactionDto.setTenantID(entitlementTransaction.getTenantID());
            entitlementTransactionDto.setCustomer(entitlementTransaction.getCustomer());
            entitlementTransactionDto.setStorage(entitlementTransaction.getStorage());
            entitlementTransactionDto.setCpuCore(entitlementTransaction.getCpuCore());
            entitlementTransactionDto.setUserCount(entitlementTransaction.getUserCount());
            entitlementTransactionDto.setStatus(entitlementTransaction.getStatus());
            
            entitlementTransactionDtoNews.add(entitlementTransactionDto);
        }
        return entitlementTransactionDtoNews;
    }
    

    通过这样的方式就可以打破双向映射导致的反复查询,于是我们得到如下的正确的findAll结果如图:

    正确结果

    这个问题是由JPA导致的,在同事的帮助下用这样的方式解决了该问题,希望JPA以后能够修复这个BUG。

    相关文章

      网友评论

          本文标题:JPA 双向映射反复查询解决办法

          本文链接:https://www.haomeiwen.com/subject/pwyxhxtx.html