简体   繁体   中英

Multiple references to @OneToMany bag relationships using Hibernate

I have following (1:n) relationship: SchoolClass -> Students. SchoolClass can have multiple students, and Student can be assigned to only one SchoolClass . In Hibernate ( SchoolClass class), I have following:

    private transient List students;

    /**
     * @return Returns students.
     * @hibernate.bag lazy="true" cascade="all" where="(graduated_with_honors=0)" 
     * @hibernate.collection-key column="class_id"
     * @hibernate.collection-one-to-many class="my.project.namespace.Student"
     */
    public List getStudents() {
        if (students == null) {
            students = new Vector();
        }
        return students;
    }

Now, I want to create another method, that lists all the Students of the SchoolClass (also the ones, that graduated with honours, so graduated_with_honors can be either 0 or 1 ). I have tried following:

    private transient List students, allStudents;

    /**
     * @return Returns students.
     * @hibernate.bag lazy="true" cascade="all" where="(graduated_with_honors=0)" 
     * @hibernate.collection-key column="class_id"
     * @hibernate.collection-one-to-many class="my.project.namespace.Student"
     */
    public List getStudents() {
        if (students == null) {
            students = new Vector();
        }
        return students;
    }

    /**
     * @return Returns students.
     * @hibernate.bag lazy="true" cascade="all" 
     * @hibernate.collection-key column="class_id"
     * @hibernate.collection-one-to-many class="my.project.namespace.Student"
     */
    public List getAllStudents() {
        if (allStudents == null) {
            allStudents = new Vector();
        }
        return allStudents;
    }

But this is not good approach, because now we have two collections that are modifying one table (it would throw hibernate found shared references to a collection exception) when used.

Does anybody know how to do this? Or, is there a way, how to insert a parameter into @hibernate.bag where clause , so we would change where clause according to the situation?

Thanks in advance.

EDIT:

private transient List students;

- this have to stay the same, I have to keep it as it is.

There are many things that are wrong in your mapping:

  1. Collections should always be non-nullable:

     private List<Student> students = new ArrayList<>();
  2. Why do you use a Vector instead of a List ? The Vector is synchronized, while the ArrayList is not. Do you really want to use an entity concurrently?

  3. You can't use the term class which is reserved in java, so maybe it's better to rename it to Course .

  4. The graduated_with_honors relation can be best represented with a boolean in the Student class.

     private boolean graduatedWithHonor;

Then, you can simply query all the Student(s) which have graduated with honor:

Course course = ...;

List<Student> honourableStudents = entityManager.createQuery(
        "select s " +
        "from Student s " +
        "where s.graduatedWithHonor = true " +
        "and s.course = :course", Student.class)
.setParameter("course", course)
.getResultList();

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