简体   繁体   English

JPA @ManyToMany问题通过C表从A到B(不是双向),但是不是通过主键连接到B

[英]Issue with JPA @ManyToMany From A to B(NOT bidirectional) via C table, but the connection to B not by primary key

I have an JPA @ManyToMany issue 我有一个JPA @ManyToMany问题

I have One Main entity called Report . 我有一个称为Report主要实体。 I have several entities connect to Report with ManyToMany Relation. 我有几个实体通过ManyToMany Relation连接到Report The connection is done via extra table. 通过额外的表进行连接。 ie with @JoinTable annotation. 即与@JoinTable注解。 Each relation is lazy . 每个关系都是lazy

I have a function that fetch the report with all its relations. 我有一个函数可以获取report及其所有关系。 now, if i do fetch by accessing the property (ie mark the function as @Transcational and access to each one of the property) everything works as expected. 现在,如果我确实通过访问该属性( @Transcational该函数标记为@Transcational并访问该属性的每一个)来获取内容,则一切正常。 But , if I do 但是 ,如果我这样做

 CriteriaBuilder cb = em.getCriteriaBuilder();
 CriteriaQuery<Report> query = cb.createQuery(Report.class);
 Root<Report> report = query.from(Report.class);

 ArrayList<Predicate> preds = new ArrayList<Predicate>();
 DomainSpecification.<Report>eager().toPredicate(report, query, cb);
 preds.add(DomainSpecification.<Report>idIsEqual(id).toPredicate(report, query, cb));
 query.where(cb.and(preds.toArray(new Predicate[preds.size()])));

 query.select(report);
 List<Report> results = em.createQuery(query).setMaxResults(1).get

I get all the relations as well but One of the relation (that has been connected to another table NOT by primary key) is fetching alots times. 我得到的所有关系很好,但其中的关系 (已按主键连接到另一个表NOT)被取alots倍。 This means that the length of r.getProjects() is 13823 of the same value. 这意味着r.getProjects()的长度是相同值的13823。 ie of the same Project. 即同一项目。

I'm attaching here the relevant source from Domain Specification / Report.java / Project.java and Keyword.java (the keyword is just to show an example for an entity that works good with this kind of fetching) Maybe one can throw some light on this issues. 我在这里附上Domain Specification / Report.java / Project.javaKeyword.java的相关资源(该关键字只是为了说明一个实体,可以很好地进行这种获取),也许有人可以提出一些建议。在这个问题上。

Thanks, Oak 谢谢,橡树







Additional Information 附加信息

Code

Report.java

@Entity(name = "reports") public class Report implements Serializable, Auditing,JppDbObject {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "REPORT_ID", unique = true, nullable = false)
private Long id;

@JsonIgnore
@OneToOne(cascade = CascadeType.ALL, mappedBy = "report")
private ReportId report;
/*
 * this here for updating the reports_ids table.
 * 
 * set json ignore over this field.
 */

@Column(name = "txt", nullable = false)
private String txt;

@Column(name = "cleanTxt")
private String cleanTxt;

@CreatedDate
@Column(name = "CREATION_DATE", nullable = false)
private Date creationDate;

@LastModifiedDate
@Column(name = "LAST_MODIFIED", nullable = false)
private Date lastModified;

@Column(name = "status", nullable = false)
private Integer status;

@CreatedBy
@JsonIgnore
@ManyToOne(optional = true)
@JoinColumn(name="CREATOR_ID", referencedColumnName = "ID")
private User createdBy;

@LastModifiedBy
@ManyToOne(optional = true)
@JoinColumn(name="MODIFIER_ID", referencedColumnName = "ID")
private User modifiedBy;

@JsonIgnore
@OneToMany(mappedBy="reportCommented")
//TODO make sure comments works good with lazy. @OneToMany(fetch=FetchType.EAGER, mappedBy="reportCommented")
private Set<ReportComment> comments;

/* this is the important line*/
@JsonIgnore
@ManyToMany
@JoinTable(
      name="reports_projects",
      joinColumns={@JoinColumn(name="report_id", referencedColumnName="REPORT_ID")},
      inverseJoinColumns={@JoinColumn(name="project", referencedColumnName="CODE")})
private List<Project> projects;

@JsonIgnore
@ManyToMany
@JoinTable(
        name="reports_keywords",
        joinColumns={@JoinColumn(name="report_id", referencedColumnName="REPORT_ID")},
        inverseJoinColumns={@JoinColumn(name="keyword_id", referencedColumnName="keyword_id")})
private Set<Keyword> keywords;

Project.java

@Entity(name = "projects") public class Project implements Serializable{ @Entity(name =“ projects”)公共类Project实现了Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "PROJECT_ID")
private long id;

@Column(name = "CODE", nullable = false,unique = true)
private String code;

@Column(name = "DESCRIPTION", nullable = false)
private String description;

@CreatedDate
@Column(name = "CREATION_DATE", nullable = false)
private Date creationDate;

@JsonIgnore
@OneToMany(mappedBy = "id.proj", cascade = {CascadeType.ALL}, orphanRemoval=true)
private List<ProjectPermission> permissions;

Domain Specification

public class DomainSpecification { 公共类DomainSpecification {

public static <T> Specification<T> eager() {

    return new Specification<T>() {

        @Override
        public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            for (PluralAttribute<? super T, ?, ?> fetch : root.getModel().getPluralAttributes()) {
                root.fetch(fetch, JoinType.LEFT);
            }
            query.distinct(true);
            return null;
        }

    };
}

public static <T> Specification<T> idIsEqual(final Long id) {

    return new Specification<T>() {

        @Override
        public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                        return cb.equal(root.get("id"),id);

        }

    };
}

} }

System 系统

  • Spring (4.0.6.RELEASE) 春天(4.0.6.RELEASE)
  • Spring-Data (1.6.2.RELEASE) 弹簧数据(1.6.2.RELEASE)
  • Hibernate EntityManager (4.3.6.Final - 4.2.1) Hibernate EntityManager(4.3.6。最终版-4.2.1)
  • MySQl Connector (5.1.13) MySQl连接器(5.1.13)
  • cglib (3.1) cglib(3.1)
  • aspectj (1.8.1) Aspectj(1.8.1)

Seems that the issue was connecting two table not via primary key. 似乎问题出在不是通过主键连接两个表。 Although this can be done via normal sql. 虽然这可以通过普通的sql完成。 JPA produces unexpected result for me. JPA为我产生了意外的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM