Bi-directional many to many with link entity

Hi folks. I am attempting to create a many to many relationship in Hibernate. The model is as follows:

Movie - MovieEmployee - Employee

Movie, movieEmployee, and employee are all tables in my database, where movieEmployee serves as the “join” table. I’m running tests for retrievals of some data that I manually inserted into my database (my “seed” data);

This is how I’m querying for a particular move in my database:

    	Movie returnedMovie = session.createSelectionQuery("select m from Movie m where m.moviePrimaryKey.originalTitle = :movie", Movie.class)
    			.setParameter("movie", "Alien 3")
    			.getSingleResultOrNull();

The associations are lazyily loaded, and when I’m debugger mode I notice that when I look at my

returnedMovie

variable and dig into the associated entity “employees” (MovieEmployee entity) I’ll notice that I can recursively keep going from MovieEmployee to Employee to MovieEmployee to Movie to MovieEmployee to Employee etc. How do I stop this from happening? When I create additional tests I want to control how many “levels” the queries retrieve. For example I’d like to only return the Movie, and MovieEmployees and stop there. I don’t want to see the entire Employe entity in MovieEmployees.

@Entity
@Table(name = "movies")
public class Movie {
	@EmbeddedId
	private MoviePrimaryKey moviePrimaryKey;
	@Column(name = "alternative_title")
	private String alternativeTitle;
	@Column(name = "motion_picture_rating")
	private String motionPictureRating;
	@Column(name = "motion_picture_rating_desc")
	private String motionPictureRatingDesc;
	@Column(name = "running_time")
	private Integer runningTime;
	private String synopsis;
	private String hook;
	private String themes;
	private Integer budget;
	@Column(name = "box_office")
	private Integer boxOffice;
	private Double score;
	@Column(name = "img_location")
	private String imgLocation;
	
	@OneToMany(
			mappedBy = "movie",
			orphanRemoval = true
		)
	List<MovieEmployee> employees = new ArrayList<>();	
	
	public Movie() {
	}
        /** constructors and getter/setters omitted for brevity **/
	public void addEmployee(Employee employee, String jobPosition, String role) {
		MovieEmployee movieEmployee = new MovieEmployee(this, employee, jobPosition, role);
		employees.add(movieEmployee);
		employee.getMovieEmployees().add(movieEmployee);
	}
	
	public void removeEmployee(Employee employee) {
		MovieEmployee movieEmployee = new MovieEmployee(this, employee);
		employees.remove(movieEmployee);
		employee.getMovieEmployees().remove(movieEmployee);

		movieEmployee.setEmployee(null);
		movieEmployee.setMovie(null);
	}

// Movie composite key class
@Embeddable
public class MoviePrimaryKey implements Serializable {

	private static final long serialVersionUID = -1333454840943927255L;
	@Column(name = "original_title")
	private String originalTitle;
	@Column(name = "release_date")
	private LocalDate releaseDate;

Join/reference entity

@Entity
@Table(name = "movies_employees")
public class MovieEmployee {
	
	@Id
	@ManyToOne
	private Movie movie;
	@Id
	@ManyToOne
	private Employee employee;
	@Column(name = "job_position")
	private String jobPosition;
	private String role;
	
	public MovieEmployee() {
	}

Employee entity

@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="employeePrimaryKey")
@Table(name = "employees")
public class Employee {
	@EmbeddedId
	private EmployeePrimaryKey employeePrimaryKey;
	@Column(name = "birth_date")
	private LocalDate birthDate;
	@Column(name = "country_of_origin")
	private String countryOfOrigin;
	private String synopsis;
	@Column(name = "popularity_ranking")
	private Integer popularityRanking;
	@Column(name = "img_location")
	private String imgLocation;
	
	@OneToMany(
			mappedBy = "employee",
			orphanRemoval = true,
			cascade = CascadeType.ALL
		)
	List<MovieEmployee> movieEmployees = new ArrayList<>();

@Embeddable
public class EmployeePrimaryKey implements Serializable {
	
	private static final long serialVersionUID = 367980327517397257L;
	@Column
	private String name;
	@Column(name = "identical_name_id")
	private int identicalNameId;

	public EmployeePrimaryKey() {
	}

Hello @blessedmaker, if I understand your need correctly you might want to look at the max_fetch_depth configuration property.

Are you sure? In your mapping for MovieEmployee, both @ManyToOne associations are not defined as FetchType.LAZY. Also, if your query dereferences an association path, this will need to be (inner) joined for the query to work.