简体   繁体   中英

JPA Hibernate one to many

Really confused by how one to many works in JPA, all the documents that I read, uses both one to many and many to one in their example, and I don't know if they are necessary or not, and it doesn't work when I tried it.

My question is, suppose I have two tables, and I want to populate the College object using findCollegeData() method, so that all the student in this college are in a list when I initialize the object.

Below is my approach, I am able to store all the students in the college list using storeCollegeData() method, but I am not able to retrieve the college object fully, the student list is always empty, even though the data is in the database, and it works if I try to search for student using college name directly.

public static EntityManager entityManager = something;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public College {
    @Id   
    @GeneratedValue(strategy= GenerationType.AUTO)
    private int cId;
    private String collegeName;
    private int numOfStudent;

    @OneToMany(mappedBy="collegeName", cascade=CascadeType.ALL, orphanRemoval=true)
    private List<Student> studentList = new ArrayList<>();
}


@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public Student {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private int sId;
    private String name;
    private String collegeName;
    private String city;
}


// college.getStudentList is always empty and I don't know why
public findCollegeData(String collegeName) {
    College college = entityManager.find(College.class, collegeName);
}

// Student data in the studentList are inserted into student table
public storeCollegeData(College college) {
    entityManager.persist(college);
}

// This method works
public findStudent(String collegeName) {

    CriteriaBuilder cb = provider.get().getCriteriaBuilder();
    CriteriaQuery<Student> query = cb.createQuery(Student.class);
    Root<Student> student = query.from(Student.class);

    query.where(
            cb.and(
                    cb.equal(student.get("collegeName"), collegeName)
            )
    );

    JobStatisticDB Student = provider.get().createQuery(query).getSingleResult();
}

Am i missing something??? Is join more appropriate than map here??? I dont know wat to do man

EDITED: Got it to work by changing both of the collegeName as the primary key of table by adding @Id annotation, however though, how can I add an sId and cId to the table, so they can have duplicate college name???? Right now, I can't have duplicate college with the same name, and student that that goes to the same college!

Final Edited: Changed database design to use foreign key see solution below

The field you reference in mappedBy must contain a value that equates to College 's id field. Change it to collegeName instead of city , and it should work.

The accepted answer is incorrect: you define relationships between entities . The mappings should be as below for a bi-directional @OneToMany

College:

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public College {
    @Id   
    @GeneratedValue(strategy= GenerationType.AUTO)
    private int cId;
    private String collegeName;
    private int numOfStudent;

    @OneToMany(mappedBy="college", cascade=CascadeType.ALL, orphanRemoval=true)
    private List<Student> studentList = new ArrayList<>();
}

Student:

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public Student {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private int sId;
    private String name;
    private String city;

    //student table has a FK column college_id 
    @ManyToOne
    @JoinColumn(name = "college_id")
    private College college;
}

EntityManager find() takes the PK as an argument:

public findCollege(int collegeId) {
    College college = entityManager.find(College.class, collegeId);
    college.getStudents(); //will be populated
}

public findStudent(int studentId) {
    Student student = entityManager.find(Student.class, studentId);
    student.getCollege(); //will be populated
    student.getCollege().getStudents(); //will be populated
}

If you want to find a college by name create a JPQL or Criteria query:

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