简体   繁体   中英

Hibernate many-to-many withe extracolumn criteria problems

I followed this tutorial to implement in my domain model a many-to-many relationship with an extra column. It works great but I'm unable to create a criteria to query a field within the left side of my relation.

Taking this code

        @Entity
        @Table( name = "projects")
        public class Project implements Cloneable, Serializable{

            private Long id;
            private String name;
            private Set<ProjectOrganization> projectOrganizations = new HashSet<ProjectOrganization>(0);

            @Id
            @GeneratedValue(strategy = GenerationType.AUTO)
            @Column(nullable = false)
            public Long getId() {
                return this.id;
            }


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


            @Column(name = "name", length = 255, nullable = false)
            public String getName() {
                return this.name;
            }


            public void setName(String name) {
                this.name = name;
            }


            @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.project")
            @Cascade(value = { CascadeType.ALL })
            public Set<ProjectOrganization> getProjectOrganizations() {
                return this.projectOrganizations;
            }


            public void setProjectOrganizations(Set<ProjectOrganization> organizationProjects) {
                this.projectOrganizations = organizationProjects;
            }

        }





    @Entity
    @Table(name = "projects_has_organizations")
    @AssociationOverrides({ @AssociationOverride(name = "pk.project", joinColumns = @JoinColumn(name = "projects_id")), 
                            @AssociationOverride(name = "pk.organization", joinColumns = @JoinColumn(name = "organizations_id"))
                            })
    public class ProjectOrganization implements Cloneable, Serializable {


        private ProjectOrganizationPK pk = new ProjectOrganizationPK();
        private OrganizationRolesEnum role;

        public ProjectOrganization() {
        }

        @Transient
        public Organization getOrganization() {
            return getPk().getOrganization();
        }

        public void setOrganization(Organization organization) {
            getPk().setOrganization(organization);
        }

        @EmbeddedId
        public ProjectOrganizationPK getPk() {
            return pk;
        }

        public void setPk(ProjectOrganizationPK pk) {
            this.pk = pk;
        }

        @Transient
        public Project getProject() {
            return getPk().getProject();
        }

        public void setProject(Project project) {
            getPk().setProject(project);
        }

        @Enumerated(EnumType.STRING)
        @Column(nullable = false, length = 50)
        public OrganizationRolesEnum getRole() {
            return role;
        }

        public void setRole(OrganizationRolesEnum role) {
            this.role = role;
        }

    }

    @Embeddable
    public class ProjectOrganizationPK implements Cloneable, Serializable {

        /** Generated serial version UID */
        private static final long serialVersionUID = -4534322563105003365L;

        private Organization organization;
        private Project project;

        @ManyToOne
        public Organization getOrganization() {
            return organization;
        }

        public void setOrganization(Organization organization) {
            this.organization = organization;
        }

        @ManyToOne
        public Project getProject() {
            return project;
        }

        public void setProject(Project project) {
            this.project = project;
        }
    }

    @Entity
    @Table(name = "organizations")
    public class Organization implements Cloneable, Serializable {

        private Long id;
        private String name;
        private Set<ProjectOrganization> projectOrganizations = new HashSet<ProjectOrganization>(0);

        public Organization() {
        }


        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(nullable = false)
        @Override
        public Long getId() {
            return this.id;
        }

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

        @Column(name = "name", nullable = false, length = 255)
        @NotNull(message = "A name is required!")
        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }


        @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.organization")
        public Set<ProjectOrganization> getProjectOrganization() {
            return this.projectOrganizations;
        }


        public void setProjectOrganization(Set<ProjectOrganization> projectOrganizations) {
            this.projectOrganizations = projectOrganizations;
        }
}

I want is to create a criteria to select a Project which has an organization with a requested name.

final Criteria crit = getSession().createCriteria(Project.class);
crit.createCriteria("projectOrganizations", "projectOrganization").
 createAlias("pk.organization", "organization").
  add( Restrictions.like("organization.name", "TEST"));

But when i run this code i have this error

2012-10-19 10:38:43,095 ERROR [org.hibernate.util.JDBCExceptionReporter] Unknown column 'organizati2_.name' in 'where clause'

and the sql query generated by hibernate is incomplete, doesn't join projects_has_organizations.organization with organization.id.. So it can't find column organization.name

SELECT
   ....
FROM
    projects this_
INNER JOIN projects_has_organizations projectorg1_ ON this_.id = projectorg1_.projects_id
WHERE
    projectorg1_.role =?
AND organizati2_. NAME LIKE ?
ORDER BY
    this_.publish_date DESC

What's wrong with this code? How can i build query using criteria ?

I suspect that the problem is due to lazy fetching, try explicitly telling hibernate to eagerly fetch the property you need. This is done with the method

.setFetchMode("propertyName", FetchMode.EAGER)

So, in otherwords, try eagerly fetch the organisation property :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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