【问题标题】:How to correctly annotate JPA enities with @OneToOne?如何使用@OneToOne 正确注释 JPA 实体?
【发布时间】:2016-09-30 15:07:01
【问题描述】:

同学们,我有两张桌子,选择获取CHAIN

SELECT OD_CHAINS_REQ.CHAIN FROM OD_CHAINS_REQ JOIN od_face_accs ON od_face_accs.ID = OD_CHAINS_REQ.ACCOUNT WHERE od_face_accs.ACNT='1608290029' ORDER BY OD_CHAINS_REQ.NUM;

OD_CHAINS_REQtable 中的记录少于 10 条,od_face_accstable 中的记录超过 1000 条。

我正在尝试通过 JPA 执行此选择。但是,据我了解,我需要创建实体OdChainsReqEntity

    @Entity
    @Table(name = "OD_CHAINS_REQ", schema = "", catalog = "")
    @IdClass(OdChainsReqEntityPK.class)
    public class OdChainsReqEntity {
        private Integer chain;
        private Integer num;
        private Integer account;

        @Id
        @Column(name = "CHAIN")
        public Integer getChain() {
            return chain;
        }

        public void setChain(Integer chain) {
            this.chain = chain;
        }

        @Basic
        @Column(name = "NUM")
        public Integer getNum() {
            return num;
        }

        public void setNum(Integer num) {
            this.num = num;
        }

        @Id
        @Column(name = "ACCOUNT")
        public Integer getAccount() {
            return account;
        }

        public void setAccount(Integer account) {
            this.account = account;
        }


    @OneToOne
    @JoinColumn(name = "ACCOUNT", referencedColumnName = "ID")
    private OdFaceAccsEntity odFaceAccsEntity;
    public OdFaceAccsEntity getOdFaceAccsEntity() {
        return odFaceAccsEntity;
    }

    public void setOdFaceAccsEntity(OdFaceAccsEntity odFaceAccsEntity) {
        this.odFaceAccsEntity = odFaceAccsEntity;
    }

    /*@Overrides*/*/

}

OdFaceAccsEntity实体:

@Entity
@Table(name = "OD_FACE_ACCS", schema = "", catalog = "")
public class OdFaceAccsEntity {
    private Integer id;
    private String acnt;



    @Id
    @Column(name = "ID")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }



    @Basic
    @Column(name = "ACNT")
    public String getAcnt() {
        return acnt;
    }

    public void setAcnt(String acnt) {
        this.acnt = acnt;
    }

    /*@Overrides*/


    @OneToOne
    @JoinColumn (referencedColumnName = "ACCOUNT")
    private OdChainsReqEntity odChainsReqEntity;

    public OdChainsReqEntity getOdChainsReqEntity() {
        return odChainsReqEntity;
    }

    public void setOdChainsReqEntity(OdChainsReqEntity odChainsReqEntity) {
        this.odChainsReqEntity = odChainsReqEntity;
    }

}

所以我正在尝试使用测试来获取链

 @Test
    public void getChainByDepoAcc() throws Exception {

        OdFaceAccsEntity odFaceAccsEntity = new OdFaceAccsEntity();
        odFaceAccsEntity.setAcnt("1608290029");


        List<OdFaceAccsEntity> odFaceAccsEntities = odFaceAccsDAO.getAcc(odFaceAccsEntity);

        for (int i = 0; i < odFaceAccsEntities.size(); i++) {
            LOG.info(odFaceAccsEntities.get(i).getId());
            LOG.info(odFaceAccsEntities.get(i).getOdChainsReqEntity().getChain());
        }
    }

但它返回异常:

原因:org.hibernate.MappingException:无法确定类型 对于:com.alcap.app.JPA.Entities.OdFaceAccsEntity,在表中: OD_CHAINS_REQ,对于列: [org.hibernate.mapping.Column(odFaceAccsEntity)]

如何正确指定实体中的关联以避免异常?

更新 我尝试过的最后一个 DAO 实现:

  @Transactional(value = "txMan", readOnly = true)
    public List <OdChainsReqEntity> getOdChainsReqByDEPOAcc(String in$depoAccnt) {
        Query query = em.createQuery("SELECT cre FROM OdChainsReqEntity cre " +
            "join OdFaceAccsEntity fae on fae.id = cre.account "+
           "where fae.acnt = :depoAcc");
         query.setParameter("depoAcc", in$depoAccnt);
        List<OdChainsReqEntity> result =  query.getResultList();
        return result;
    }

我也试过这个(但我不知道它是否适合join选择):

public List<OdChainsReqEntity> getOdChainsReqByAnyParam(OdChainsReqEntity odChainsReqEntity) {

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<OdChainsReqEntity> criteriaQuery = cb.createQuery(OdChainsReqEntity.class);
        Root<OdChainsReqEntity> entityRoot = criteriaQuery.from(OdChainsReqEntity.class);

        Predicate criteria = cb.conjunction();

        if (odChainsReqEntity.getChain() != null) {Predicate p = cb.equal(entityRoot.get("chain"), odChainsReqEntity.getChain()); criteria = cb.and(criteria, p);}
        if (odChainsReqEntity.getNum() != null) {Predicate p = cb.equal(entityRoot.get("num"), odChainsReqEntity.getNum()); criteria = cb.and(criteria, p);}
        if (odChainsReqEntity.getAccount() != null) {Predicate p = cb.equal(entityRoot.get("account"), odChainsReqEntity.getAccount()); criteria = cb.and(criteria, p);}


        criteriaQuery.where(criteria);
        List<OdChainsReqEntity> result = em.createQuery(criteriaQuery).getResultList();

        return result;

    }

【问题讨论】:

    标签: java hibernate jpa annotations


    【解决方案1】:

    您尚未发布您的 DAO 实现。假设它是正确的,则可能是以下问题之一:

    1. 您对access type 的定义不一致。您正在将映射注释(@Column@OneToOne、...)放在 getter 方法以及规范未定义的实体的字段上。因此,将映射注释移动到字段或 getter 上,但不要同时移动:

      @Entity
      @Table(name = "OD_FACE_ACCS", schema = "", catalog = "")
      @Access(AccessType.PROPERTY)
      public class OdFaceAccsEntity {
          private Integer id;
          private String acnt;
          private OdChainsReqEntity odChainsReqEntity;
      
          @Id
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public String getAcnt() {
              return acnt;
          }
      
          public void setAcnt(String acnt) {
             this.acnt = acnt;
          }
      
          /*@Overrides*/
      
          @OneToOne(mappedBy = "odFaceAccsEntity")
          public OdChainsReqEntity getOdChainsReqEntity() {
              return odChainsReqEntity;
          }
      
          public void setOdChainsReqEntity(OdChainsReqEntity odChainsReqEntity) {
              this.odChainsReqEntity = odChainsReqEntity;
           }
      
      }
      
      
      
      @Entity
      @Table(name = "OD_CHAINS_REQ", schema = "", catalog = "")
      @IdClass(OdChainsReqEntityPK.class)
      @Access(AccessType.PROPERTY)
      public class OdChainsReqEntity {
          private Integer chain;
          private Integer num;
          private Integer account;
          private OdFaceAccsEntity odFaceAccsEntity;
      
          // the rest of the code here
      
          @OneToOne
          @JoinColumn(name = "ACCOUNT", referencedColumnName = "ID")
          public OdFaceAccsEntity getOdFaceAccsEntity() {
              return odFaceAccsEntity;
          }
      
          // the rest of the code
      
      }
      

    如您所见,我在 getter 方法上移动了所有必要的映射注解(我只是删除了一些注解以节省空间,因为它们默认存在)。

    1. 第二个问题是您在两个实体上都放置了@JoinColumn 注释,这是不正确的。您必须将此注释仅放置在关系的一侧,该一侧应该是关系的所有者;在一对一的关系中,将注释放在哪一侧并不重要。需要将关系的另一端映射为@OneToOne(mappedBy = "")。我刚刚将OdFaceAccsEntity 实体设置为关系的反面并相应地进行了更改(参见上面代码中的@OneToOne)。如果您不希望该实体是反面,只需反转注释

    以下是JPA 2.0 specification 的部分内容,您可以阅读以了解如何正确映射:

    • 2.3 访问类型
    • 2.10.1 双向 OneToOne 关系

    【讨论】:

    • 试试这个查询而不是你的:SELECT cre FROM OdChainsReqEntity cre JOIN cre.odFaceAccsEntity fae where fae.acnt = :depoAcc。 (这是内连接 => 如果表没有匹配的列,您将得到空结果集;在这种情况下,您可以使用左连接。我认为条件部分不完整;但请先尝试这个。
    • 我将@OneToOne(mappedBy = "odFaceAccsEntity") 添加到OdFaceAccsEntity 类中,但接收到弹出窗口Cannot resolve attribute 'odFaceAccsEntity'
    • 呃...谢谢@ujulu。祝你一切顺利。
    猜你喜欢
    • 2017-01-24
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 2010-12-22
    相关资源
    最近更新 更多