how can I create the work_with class in springBoot. I have tried my approch is that I have created the manytomany mapping between employee and client class but I was not able to create new colunm which is total_sales within work_with. Is there any way I can Create the new colunm during mapping and is my approch is right or wrong ? if not what should I do to create the works_with table class/entity and also want to add ON DELETE CASCADE.
I want to create the Entity class just like I have done in below image.
#Entity
#Table(name="posts")
#NoArgsConstructor
#Getter
#Setter
public class **Post** {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name="post_tittle",length = 100, nullable = false)
private String tittle;
#Column(name="post_image", nullable = false)
private String imageName;
private String content;
private Date addedDate;
#ManyToOne
#JoinColumn(name="category_id")
private Category category;
#ManyToOne
private User user;
#OneToMany(mappedBy = "post",cascade = CascadeType.ALL)
private Set<Comment> comments = new HashSet<>();
}
You can find a lot of examples and articles online that explain how ManyToMany mappings work. Just search with your favorite search engine for "JPA ManyToMany" and you will find an article like the following: https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany
Related
I was trying to do #ManyToMany association and it worked when I tried to do relations like
User can have multiple group and one group can multiple user.. it worked ,and hibernate created custom table based on it automatically and it did its worked. later I had to add more columns to the association table so I followed a article and set the things up as per that, which worked pretty good.
I am using SpringBoot and is using SpringDataJPA
Here is my implementation :
#Entity
#Table(name = "USERS")
public class User {
#Id
#GeneratedValue
private long id;
private String username;
private String password;
private String email;
#OneToMany(mappedBy = "user")
private Set<UserGroup> userGroups = new HashSet<UserGroup>();
}
#Entity
#Table(name = "GROUPS")
public class Group {
#Id
#GeneratedValue
private long id;
private String name;
#OneToMany(mappedBy = "group")
private Set<UserGroup> userGroups = new HashSet<UserGroup>();
}
#Entity
#Table(name = "USERS_GROUPS")
public class UserGroup {
#Id
#GeneratedValue
private long id;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "USER_ID")
private User user;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "GROUP_ID")
private Group group;
// additional fields
private boolean activated;
private Date registeredDate;
}
User user = new User("tommy", "ymmot", "tommy#gmail.com");
Group group = new Group("Coders");
User persistedUser = userRepository.save(user);
Group persistedGroup = groupRepositry.save(group);
UserGroup userGroup = new UserGroup();
userGroup.setGroup(persistedGroup);
userGroup.setUser(persistedUser);
userGroup.setActivated(true);
userGroup.setRegisteredDate(new Date());
userGroupRepository.save(userGroup);
Now how to write a SpringData equavalent methd name for getting user's
group where the user is active ? i.e I make user active = false when
some one deletes users from a group instead of deleting the entry from
the user_group assossiation table.
Can we do it on the userRepository?
I think that you would like to have repository similar to this one:
public interface UserGroupRepository extends JpaRepository<UserGroup, Long> {
List<UserGroup> findAllByUserAndActivatedIsTrue(User user);
}
This method will give you List of all groups that this user is assigned to and is active.
If you would like to parameterize also activated field, you should instead use
List<UserGroup> findAllByUserAndActivated(User user, boolean activated);
I hope that this helps you. Good luck.
And btw, I recommend reading this:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
Helps a lot
I am trying to solve JPA problem. I have 2 main entities - CameraItem and Chain (which represents ordered list of cameras)
Now there have to be 2 #ManyToMany relationships between CameraItem and Chain.
Each CameraItem has at least one parent Chain. As one CameraItem can belong to different Chains, and each Chain can have multiple CameraItems this is the first simple direct #ManyToMany relationship.
Chains can be connected with each other via CameraItem. In other words, CameraItem is holding the connection between Chains. But this is not simple #ManyToMany relationship, because we also need information about direction of the Chains connection. So it is #ManyToMany relationship with new Entity as Baeldung describes here https://www.baeldung.com/jpa-many-to-many. Entity ConnectionPoint is holding the information about the direction as a String.
I paste the classes here:
CHAIN CLASS:
#Entity
#Table(name = "chain")
public class Chain {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#NotBlank(message = "Chain name is mandatory")
private String name;
#Column(name = "PLANT_NAME")
private String plantName;
private String description;
private String status;
private Boolean hasPlant;
#CreationTimestamp
#Column(name = "creation_time")
private LocalDateTime creationTime;
#OneToMany(mappedBy = "camera_item")
private List<CameraItem> cameraItems = new ArrayList<>();
#OneToMany(mappedBy = "chain")
Set<ConnectionPoint> connectionPoints;
CAMERA ITEM CLASS:
#Entity
#Table(name = "camera_item")
public class CameraItem {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#ManyToOne
#JoinColumn
private Camera camera;
private String name;
private Integer positionInChain;
#ManyToMany(mappedBy = "cameraItems", fetch = FetchType.LAZY)
private List<Chain> parentChainIds;
#OneToMany(mappedBy = "cameraItem")
Set<ConnectionPoint> connectionPoints;
CONNECTION POINT CLASS:
#Entity
#Table(name = "connection_point")
public class ConnectionPoint {
#Id
private Long id;
#Column(name = "direction")
private String direction;
#ManyToOne
#JoinColumn(name = "chain")
private Chain chain;
#ManyToOne
#JoinColumn(name = "camera_item")
private CameraItem cameraItem;
When I run the application I get this error:
org.hibernate.AnnotationException: mappedBy reference an unknown
target entity property:
no.trafsys.videodashboard.model.entity.CameraItem.camera_item in
no.trafsys.videodashboard.model.entity.Chain.cameraItems
Does somebody know where the problem can be?
I use #OneToMany annotations in Chain and CameraItem entities and #ManyToOne in ConnectionPoint like Baeldung in his tutorial.
Thank you in advance for any help
I don't think there is issue in ConnectionPoint. I think the issue is that:
In Chain class,
#OneToMany(mappedBy = "camera_item") // One-to-Many defined here
private List<CameraItem> cameraItems = new ArrayList<>();
while in CameraItem class, corresponding property is defined as follow:
#ManyToMany(mappedBy = "cameraItems", fetch = FetchType.LAZY) // Many-To-Many
private List<Chain> parentChainIds;
Try changing the mapping type to #ManyToMany in Chain class as well. It might work.
PS: I am not entirely sure of this, but this feels like the issue[incorrect mapping type]. Wanted to add this as a comment, but due to space issues, adding it as an answer.
#Entity
#Table(name = "chain")
public class Chain {
//..
#OneToMany(mappedBy = "camera_item")
private List<CameraItem> cameraItems = new ArrayList<>();
//..
}
mappedBy parameter can only be in one side of the relation. I suspect camera_item is database table column name. So your cameraItems needs #JoinTable(name = "camera_item"... annotation
I am using hibernate to represent a database with the three major Entities User, Project and Comment. User and Project inherit from Base class. The Project also holds an unlimited amount of comments.
In the POJO i tried to represent the collection of comments associated by a project by with a List<Comment>.
My major problem is, when i i go and take a project which holds a number of comment references within the list java will throw an IllegalArgumentException saying, that it cant access the id field of comment, as it only gets an ArrayList.
Caused by: java.lang.IllegalArgumentException: Can not set int field com.project.objects.Comment.id to java.util.ArrayList
My classes are as followed - without Constructor/Setter/Getter as these are plain simple:
#MappedSuperclass
public abstract class Base {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String name;
#Column
private String longDesc;
#Column
private String briefDesc;
#Column
#ElementCollection(targetClass=String.class)
private List<String> goals;
#Column
private String picture;
#Column
private int cType;
#Entity(name = "Project")
#Table(name = "project")
public class Project extends Base {
#Column
private String start;
#Column
private String end;
#Column
private String manager;
#ElementCollection(targetClass=Comment.class)
#ManyToOne(targetEntity = Comment.class, fetch = FetchType.EAGER)
#JoinColumn(name = "comment_id")
private List<Comment> comments;
#Entity(name = "Comment")
#Table(name = "comment")
public class Comment {
#Id
#Column(name="comment_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String comment;
#Column
private int rating;
#Column
private int pcuser;
#Column
private int cType;
Your 1:N association is wrong, as it is actually a N:1 right now. The correct would be:
Entity(name = "Project")
#Table(name = "project")
public class Project extends Base {
#Column
private String start;
#Column
private String end;
#Column
private String manager;
#OneToMany(mappedBy = "project", fetch = FetchType.EAGER)
private List<Comment> comments;
And in your Comment class:
#Entity(name = "Comment")
#Table(name = "comment")
public class Comment {
#Id
#Column(name="comment_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String comment;
#Column
private int rating;
#Column
private int pcuser;
#Column
private int cType;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "id_project", nullable = false)
private Project project;
// THIS is the required and obrigatory mapping that you forgot.
// It's the foreing key itself
Disclaimer
I've never actually used Hibernate with inheritance before (usually, it's desnecessarily complex and also inefficient for a relational database) but check `https://www.baeldung.com/hibernate-inheritance` and `https://marcin-chwedczuk.github.io/mapping-inheritance-in-hibernate` for more information.
You're using a #ManyToOne annotation for comments but it should be #OneToMany.
In order to use #OneToMany you would have to have a column called something like project_id in the comment table, which you would reference from the #OneToMany field. Do you have that?
If not, how are you linking comments to projects in your database?
By the way, it's really easy to create poorly-performing systems with Hibernate, because it tends to obscure the cost of hitting the database. You've said that there can be any number of comments associated with a project. Do you really want to load them all every time the code loads a project? Let's say you just want a list of projects, for example to populate a selection list. Simply loading that list will also load every comment in the system, even though you don't actually need them.
Comment is an entity and should not be used with the #ElementCollection inside the Project entity.
Your relationship is a project to many comments. #OneToMany
I have two table with many-to-one relationship. Example is, I have Office table and Employee table. One Employee belong to one Office and one Office belong to many Employee.
Office
#Entity(name = "office")
#Table(name = "office", uniqueConstraints = {#UniqueConstraint(columnNames = {"id"})})
public class Office {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "office_name", nullable = false)
private String officeName;
}
Employee
#Entity(name = "employee")
#Table(name = "employee", uniqueConstraints = {#UniqueConstraint(columnNames = {"id"})})
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "employee_name", nullable = false)
private String employeeName;
#ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
#JoinColumn(name = "office_id", referencedColumnName = "id", nullable = false)
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Office office;
}
OfficeDto
public class OfficeDto {
private Long id;
private String officeName;
}
EmployeeDto
public class EmployeeDto {
private Long id;
private String employeeName;
private OfficeDto office;
}
With above way of defining the entity and the DTO, when I do employee.findAll(), the JSON result is also include the detail of the office data.
Is there any way that I could achieve (objective):
When do saving new employee, I just have to mention the id of the office.
When do findAll employee, I could choose whether I want to gove the id only or also with the entire object to the client.
Because, with current situation, I think I need to define two employee DTO. First one is contain the entire office data (like the code of EmployeeDto) and the second one is replace private OfficeDto office with private int office.
The second problem you can solve by projection : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
Or just specific mapper to DTO, for mapping you can use mapstruct : http://mapstruct.org/documentation/installation/
For the first problem i found some answer in stack, but you need verify it : JPA many-to-one relation - need to save only Id
I'm trying to learn Hibernate with this simple example but I'm having so trouble with the foreign key which remains "null" in the database.
#Entity
#Table(name = "tb1")
public class Track {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="id_tb1", unique= true)
private int id_tb1;
#Column(name = "title")
private String title;
#ManyToOne
#JoinColumn(name="id_tb2")
private tb2 cd;
And this is the second class
#Entity
#Table(name = "tb2")
public class CD {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="id_tb2", unique = true)
private int id_tb2;
#Column(name="title")
private String title;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,mappedBy = "cd")
private List<tb1> tracks = new ArrayList<tb1>();
I save like this:
SessionFactory factory = new Configuration().configure("/resources/hibernate.cfg.xml").buildSessionFactory();
Session session1 = factory.openSession();
session1.beginTransaction();
session1.save(tb2);
session1.getTransaction().commit();
but when Isavethe id_tb2 (in the table tb1) is not set and it remains null. What I'm missing?
The problem you have to set the relation on both sides for a bidirectional relationship.
So you have to set your relationship forCD and your Track object and persist/merge them afterwards.
Without seeing to much of your code you have to do something like.
cd.getTracks().add(track);
track.setCD(cd);
session1.save(track);
session1.save(cd);
See another question for more details.
I think your type of the table2
private tb2 cd;
should be changed as
private CD cd;