hibernate many-to-many association with extra columns in join table example - java

I have 3 tables as #Entity, and 2 join tables in my spring + hibernate app.
In one of join table i have extra column. I want to take info from this info column when i take info from my main table.
Main table code:
#Entity
#Table(name = "items")
public class Items {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "crafts"
,joinColumns = #JoinColumn(name = "item_id")
,inverseJoinColumns = #JoinColumn(name = "plot_id"))
private Set<Plots> plotInfo = new HashSet<>();
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "item_materials"
,joinColumns = #JoinColumn(name = "item_id")
,inverseJoinColumns = #JoinColumn(name = "material_id"))
private Set<Materials> materialsInfo = new HashSet<>();
Table item_materials have this columns "id, item_id(fkey), material_id(fkey), expense" and one of this which names as "expense" i need to have in my final result.
How can i code my class to have "expense" in my result?
I read about #embeddable but still dont understand how to use in my project.

Don't use a #ManyToMany association. Map the join table as entity and model it similar to this:
#Entity
#Table(name = "items")
public class Items {
#OneToMany(mappedBy = "item")
private Set<Crafts> plotInfo = new HashSet<>();
}
#Entity
#Table(name = "plots")
public class Plots {
#OneToMany(mappedBy = "plot")
private Set<Crafts> items = new HashSet<>();
}
#Entity
#Table(name = "crafts")
public class Crafts {
#EmbeddedId
private CraftsId id;
#ManyToOne
#JoinColumn(name = "item_id", insertable = false, updatable = false)
private Items item;
#ManyToOne
#JoinColumn(name = "plot_id", insertable = false, updatable = false)
private Plots plot;
}
#Embeddable
public class CraftsId {
#Column(name = "item_id")
private Integer itemId;
#Column(name = "plot_id")
private Integer plotId;
// equals + hashCode
}

Related

How to use Hibernate Check constraint in this case?

I want to use check constraint to verify if there are more students in the subject more than vacancies. These are the entities:
SubjectOffer
#Entity
#SequenceGenerator(name = "SUBJECT_OFFER_SEQ", sequenceName = "SUBJECT_OFFER_SEQ")
#Table(name = "SUBJECT_OFFER", uniqueConstraints = {
#UniqueConstraint(name = "UQ_SUBJECT_OFFER_COURSE_SUBJECT_SEMESTER_CLASS", columnNames = {"COURSE_ID", "SUBJECT_ID", "SEMESTER", "CLASS_NUMBER"})})
#Check(constraints = "COUNT(STUDENT_SUBJECT_ID) <= VACANCIES")
public class SubjectOffer {
#Id
#GeneratedValue(generator = "SUBJECT_OFFER_SEQ")
#Column(name = "SUBJECT_OFFER_ID", nullable = false)
private Long id;
#OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL)
#JoinColumn(name = "STUDENT_SUBJECT_ID")
private Set<StudentSubject> studentSubjects = new HashSet<>();
//other attributes
#Column(name = "VACANCIES", nullable = false)
private int vacancies;
}
StudentSubject
#Entity
#Table(name = "STUDENT_SUBJECT")
public class StudentSubject {
#EmbeddedId
private StudentSubjectId id = new StudentSubjectId();
#MapsId("studentId")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "STUDENT_ID", nullable = false)
private Student student;
#MapsId("subjectOfferId")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "SUBJECT_OFFER_ID", nullable = false)
private SubjectOffer subjectOffer;
#Column(name = "SEMESTER", nullable = false)
private int semester;
#Column(name = "GRADE")
private BigDecimal grade;
}
I also tried column definition in Set #JoinColumn but it didn't work
SQL check constraints only work on a single table. What you want is a so called SQL assertion constraint, but no database implements that. The best you can do is to pre-create rows for the amount of vacancies and just assign students to these rows without ever creating more rows. This way, you can make sure that you only assign as many students as there are vacancies, given that you use optimistic/pessimistic locking when assigning a student.

Problem with inserting entity object with two unidirectional One to Many relationship

I have two entities, each one pointing to one single table in an postgres. The entities belong to an Spring/graddle/JPA/Hibernate web application.
#Entity
#Table(name = "STAFF")
#AttributeOverride(name = "id", column = #Column(name = "ID"))
public class StaffEntity extends AbstractEntity {
#Column(name = "NAME")
private String name;
#Column(name = "SHORT_NAME")
private String shortName;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "STAFF_GROUP_ID", referencedColumnName = "ID")
private StaffGroupEntity staffGroup;
/* More attributes, getters and setters */
#Entity
#Table(name = "STAFF_GROUP")
#AttributeOverride(name = "id", column = #Column(name = "ID"))
public class StaffGroupEntity extends AbstractEntity {
#Column(name = "NAME")
private String name;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "LEAD_ID", referencedColumnName = "ID")
private StaffEntity lead;
/* More attributes, getters and setters */
When i update with swagger the group with a lead that is already in the group i get a stackOverFlowError
java.lang.StackOverflowError: null
mapping with mapstruct

Get records from two table in relation many to many

I have two table in relation many to many
public class Repertoire {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false, unique = true)
private Integer id;
private String name;
private Integer dayWeek;
#ManyToMany(cascade = CascadeType.REMOVE)
#JoinTable(
name = "repertoire_seance",
joinColumns = { #JoinColumn(name = "repertoire_id")},
inverseJoinColumns = {#JoinColumn(name = "seance_id")}
)
List<Seance> seances = new ArrayList<>();
}
and
public class Seance {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false, unique = true)
private Integer id;
private java.time.LocalTime displayTime;
#ManyToOne
private Film film;
#Column(length=127)
private String kind;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
private Hall hall;
#OneToMany(mappedBy = "reservationSeance")
#JsonIgnore
private List<Reservation> reservations = new ArrayList<>();
}
Hibernate create linked tabel repertoire_seance is posible get seances by seancesId and repertoire.dayWeek using spring data (JpaRepository) something like that findBySeanceIdAndRepertoireDayWeek()?
You could achieve this by writing an HQL.
It would look something like this:
select s from Repertoire r inner join r.seances s where r.dayWeek ="Your Value" and s.id = "Your Id Value"

How to create transition table

I have two table Movie and Actor
#Entity
#Table(name="movie")
#Data
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false, unique = true)
private Integer MovieId;
......
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "actorId", referencedColumnName = "actorId")
private Actor actor;
}
#Entity
#Table(name = "actor")
#Data
public class Actor {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false, unique = true)
private Integer actorId;
private String firstName;
private String lastName;
#OneToMany(mappedBy = "actor", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Movie> actorMovies = new ArrayList<>();
}
Now in MySql database i have two table but I need transiet table movie_actor. Now I have Movie table and column actorId and insert only one id. I want to have relation that One Movie have many Actors.

Joining with cross-reference table in hibernate and spring

I use hibernate and spring-data. There are two tables with many-to-many relationship.
#Entity
#Table(name = "FirstEntity")
public class FirstEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "first_entity_id")
private Long id;
#Column(name = "first_entiry_name")
private String name;
/* getters and setters are below*/
}
#Entity
#Table(name = "SecondEntity")
public class SecondEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "second_entity_id")
private Long id;
#Column(name = "second_entiry_name")
private String name;
#Column(name = "second_entiry_desc")
private String description;
/* getters and setters are below*/
}
And entity for cross-reference table.
#Entity
#Table(name = "FirstSecondEntity")
public class FirstSecondEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "first_second_entity_id")
private Long id;
#Column(name = "first_entity_id")
private Long firstEntityId;
#Column(name = "second_entity_id")
private Long secondEntityId;
/* getters and setters are below*/
}
I need SELECT like this
SELECT FirstEntity.name, SecondEntity.name, SecondEntity.description FROM SecondEntity INNER JOIN FirstSecondEntity ON SecondEntity.id = FirstSecondEntity.secondEntityId INNER JOIN User ON FirstEntity.id = FirstSecondEntity.firstEntityId
i.e. I need all records from cross-reference table where instead of ids there is actual info from entities.
Inserting this query into #Query annotation in my CrudRepository-extended class doesn't work because of
ERROR [main][org.hibernate.hql.internal.ast.ErrorCounter] Path expected for join!
So I need your help.
Your join table is all screwed up. In this case, you actually don't even need the join table as a hibernate mapping:
In Second Entity add the following list:
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "FirstSecondEntity",
joinColumns = {
#JoinColumn(name = "first_entity_id",
nullable = false,
updatable = false) },
inverseJoinColumns = {
#JoinColumn(name = "second_entity_id",
nullable = false,
updatable = false) },
)
private List<FirstEntity> firstEntities;
In FirstEntity add the following list:
#ManyToMany(fetch = FetchType.LAZY,
mappedBy = "firstEntities")
private List<SecondEntity> secondEntities;

Categories

Resources