Can I map multiple database tables to a unique Entity using JPA? - java

I am trying to add multi-language to the description and title fields of one of my Entities but without success. My Entity is like below and my database is MySQL:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "project")
public class ProjectEntity implements Serializable {
#Id
#Column(name="id")
private Integer id;
#Column(name="team_size")
private Integer teamSize;
#Column(name="description")
private String description;
#Column(name="title")
private String title;
#OneToMany
private List<DetailsEntity> details;
}
I alreaady tried to add a projectDetails entity that contains the description and title, but as I need multilanguage, the Project will now have a list of ProjectDetails in my backend, what I don't need.
Here is what the projectDetails could looks like:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "project_details")
public class ProjectDetails implements Serializable {
#Id
#Column(name="id")
private Integer id;
#Column(name="title")
private String title;
#Column(name="description")
private String description;
#Column(name="language")
private String language;
#Column(name="project_id")
private Integer projectId;
}
I would like to be able to do something with the JPA repository requests, like this:
#Repository
public interface ProjectEntityRepository extends JpaRepository<ProjectEntity, Integer> {
#Query("select p from ProjectEntity p left outer join ProjectDetails d on p.id=d.project_id and d.language=:language")
List<ProjectEntity> findAllForLanguage(String language);
}
Any idea on how to change part of this to return the Project entity with values of only 1 ProjectDetails?
Thank you

Related

Extra association table is created in spring boot

I'm currently working on developing a recipe application and I'm having trouble with DB table generation.
Here are the Entity files I'm using:
// Recipe.java
#Data
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Table(name = "recipes")
public class Recipe {
#Id
#GeneratedValue
private int id;
private String name;
private String description;
private String instruction;
#ManyToOne
private User user;
#OneToMany(cascade=CascadeType.ALL)
private List<RecipeIngredient> ingredients = new ArrayList<>();
}
// Ingredient.java
#Data
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Table(name = "ingredients")
public class Ingredient {
#Id
#GeneratedValue
private int id;
private String name;
}
// RecipeIngredient.java
#Data
#Entity
#AllArgsConstructor
#NoArgsConstructor
public class RecipeIngredient {
#Id
#GeneratedValue
private int id;
#ManyToOne
private Ingredient ingredient;
private String amount;
}
Spring Boot Automatically creates tables for me but I just wanna have one table for RecipeIngredient, but it creates two tables for them.
It works perfectly fine but the thing I want is just how to make these two tables into one or make spring boot not generate one of them.
If you want recipe_ingedients table only delete recipeIngredient Entity Class and if you want to keep recipe_ingredient table remove this:
#OneToMany(cascade=CascadeType.ALL)
private List<RecipeIngredient> ingredients = new ArrayList<>();

Java Repository Query findAll() given an ID from another class (Foreign-Key)

I'm using a JPARepository called PublicationRepository and want to find all Publications from a certain Person. This Classes are connected over the Class Author.
Person Class:
#Entity
public class Person {
#Id
private String email;
private String telefon;
private String password;
#OneToMany(mappedBy = "person")
Set<Author> Author;
}
Author Class:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Author {
#Id
private int id;
#ManyToOne
#JoinColumn(name="Person_ID")
Person person;
#ManyToOne
#JoinColumn(name="Publication_ID")
Publication publication;
private String Date;
private String Writerstatus;
}
Publication Class
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Data
public class Publication {
#Id
private int id;
private String publicationname;
#OneToMany(mappedBy = "publication")
Set<Author> author;
}
And the PublicationRepository
public interface ProjektRepository extends JpaRepository<Projekt,Integer> {
}
public interface PublicationRepository extends JpaRepository<Publication,Integer> {
#Query(value = "SELECT pub.* FROM author as auth INNER JOIN publications as pub ON auth.publication_id = pub.id WHERE auth.person_id = ?1", native = true)
List<Publication> findAllPublicationsOfThisPerson(int personId);
}
Try this.
I would also recommend to annotate the entities with their table names:
#Table(name = "publication")
You use a manually build table for a Many-to-Many relationship Author
You could also delegate that to Spring Data Jpa by using #ManyToMany Annotation.
A good tutorial:
https://attacomsian.com/blog/spring-data-jpa-many-to-many-mapping

Implementing Composite (Embedded-ID) Foreign Key Relations using Spring Data JPA

Interestingly, I can't find any solution for a seemingly common scenario! So I'm asking here to learn from experienced professionals in Spring Data JPA. I'll consider using Lombok to make the sample codes more concise.
Consider a simple IMDB example web application. I've defined two simple entities as below:
#Data
#Entity
public class Movie {
#Id
#GeneratedValue
private long id;
private String title;
private int year;
private int rating;
}
#Data
#Entity
public class Actor {
#Id
#GeneratedValue
private long id;
private String firstName;
private String lastName;
private Date birthday;
private String gender;
}
Now we need a join-table to link these two entities; but this is not just a simple join-table. Other than the actor and movie columns, this table has some additional attributes. We didn't want to waste storage by adding an ID column here, instead we used a composite-key consisting of actor and movie:
#Data
#Embeddable
public class MovieActorId implements Serializable {
private Actor actor;
private Movie movie;
}
#Data
#Entity
public class MovieActor {
#EmbeddedId
private MovieActorId id;
private int salary;
private String characterName;
}
There are two Many-to-One relations here: MovieActor >-- Actor and MovieActor >-- Movie.
Now my main question is: "Assuming the above design, how should I define the #ManyToOne relationships in this design?"
NOTE: I believe if we add an additional ID column to the MovieActor join-table instead of the composite/embedded MovieActorId, the JPA code will become fairly straight-forward. But suppose we have some sort of limitation, and we need to stick to this design as much as possible.
You need to use #MapsId which provides the mapping for an EmbeddedId primary key in #ManyToOne relation
#Data
#Embeddable
public class MovieActorId implements Serializable {
private long actorId;
private long movieId;
// constructor, setter, etc
}
#Data
#Entity
public class MovieActor {
#EmbeddedId
private MovieActorId id;
#ManyToOne(cascade = CascadeType.ALL)
#MapsId("actorId")
private Actor actor;
#ManyToOne(cascade = CascadeType.ALL)
#MapsId("movieId")
private Movie movie;
...
}

Multiply ID mapping throw BaseEntity

I'm mapping classes via Hibernate and I need to map multiple ID for Relationship.
All ID's extend from BaseEntity. How can I implement multiple ID mapping for Relationship which contains Foreign Key for User in DataBase ?
Basicly fields userIdOne and userIdTwo in Relationship has to contain user's id which send request.
User extend own ID from BaseEntity.
Each time I run it - get en error:
This class [class com.mylov.springsocialnetwork.model.Relationship]
does not define an IdClass
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#MappedSuperclass
#EqualsAndHashCode
public class BaseEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
#Builder
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode(exclude = {"posts"}, callSuper = false)
#Entity
public class User extends BaseEntity {
private String userName;
private String realName;
private String email;
private String phoneNumber;
private LocalDate birthDate;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userPosted")
private Set<Post> posts = new HashSet<>();
private String password;
public User(Long id, String userName, String realName, String email, String phoneNumber, LocalDate birthDate,
Set<Post> posts, String password) {
super(id);
this.userName = userName;
this.realName = realName;
this.email = email;
this.phoneNumber = phoneNumber;
this.birthDate = birthDate;
this.posts = posts;
this.password = password;
}
}
#Builder
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Entity
public class Relationship implements Serializable {
//#Id not working
private Long userIdFrom;
//#Id
private Long userIdTo;
#Enumerated(value = EnumType.STRING)
private RelationshipStatus status;
private LocalDate friendsRequestDate;
}
It appears that you are looking to establish a Relationship between two different users. This would mean that each Relationship is an object/entity of its own and should have its very own #Id (unrelated to user IDs).
The linkage to each User that form part of this Relationship should be mapped as foreign keys instead (probably #ManyToOne and a #JoinColumn).
For example:
#Entity
public class Relationship implements Serializable {
#Id
private Long relationshipId;
#ManyToOne(...)
#ForeignKey(name="FK_USER_ONE") //for generation only, it isn't strictly required
#JoinColumn(name="from")
private Long userIdFrom;
#ManyToOne(...)
#ForeignKey(name="FK_USER_TWO") //for generation only, it isn't strictly required
#JoinColumn(name="to")
private Long userIdTo;
#Enumerated(value = EnumType.STRING)
private RelationshipStatus status;
private LocalDate friendsRequestDate;
}
Edit:
It isn't required to specify the #ForeignKey annotations. They will be used if the database tables are generated automatically (ok for testing, but usually not something you'll want in production) and will create the FOREIGN KEY constraint on the table accordingly, but JPA mapping will work fine without it, because it takes the relationships from your defined model, not from the database itself.

How to find entity using JPA(Hibernate) with condition on joined tables?

I have 3 tables, each mapped to an entity. The entities are something like this:
#Entity
#Table(name = "person")
public class Person implements Serializable {
private int id;
//other fields
}
#Entity
#Table(name = "phone")
public class Phone implements Serializable {
private int id;
private Long price;
#ManyToOne
#JoinColumn(name = "personId")
private Person person;
#ManyToOne
#JoinColumn(name = "manufacturerId")
private Manufacturer manufacturer;
//other fields
}
#Entity
#Table(name = "manufacturer")
public class Manufacturer implements Serializable {
private int id;
private String name;
//other fields
}
What I want to do is to create a method that will return a list of Persons that have phones from a specified manufacturer with the price in a specified range.
EDIT: My dao class implements EntityJpaDao . I would need a solution that would work with this implementation.
Following query will return the Samsung mobile users with phone price range.
Criteria criteria = session.createCriteria(Phone.class, "phone");
criteria.createAlias("phone.person", "person")
criteria.add(Restrictions.between("phone.price", minPrice, maxPrice));
criteria.createAlias("phone.manufacturer","manufacturer");
criteria.add(Restrictions.eq("manufacturer.name", Samsung));
criteria.setProjection(Projections.property("person"));
List<Person> persons = criteria.list();

Categories