JEE, JPA facade edit many to many relation - jpa

I'm facing an issue i can't figure out.
I got 2 entities : User and Course with a Many to Many relationship
User.java
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
#ManyToMany(cascade = CascadeType.MERGE)
#JoinTable(
name="USR_COURSES",
joinColumns=#JoinColumn(name="USR_ID", referencedColumnName="ID"),
inverseJoinColumns=#JoinColumn(name="COURSE_ID",referencedColumnName="ID"))
private List<Course> courses;
...
Course.java
#Entity
#Table(uniqueConstraints=#UniqueConstraint(columnNames="CODE"))
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String code;
private String name;
private String content;
#ManyToMany(mappedBy="courses",cascade = CascadeType.MERGE)
private List<User> users;
...
If i create a user and set him some courses, the join table will be updated with the new relations between the User and the Courses.
However if i want to edit a user by adding him courses, the join table is not update :
List<Course> test = myUser.getCourse();
test.add(facade.find(1l));
myUser.setCourse(test);
userFacade.edit(myUser);
I'm using NetBean and the AbstractFacade generated.
Thanks for helping !

In order for the cascade to work in that case you would need to set dependencies in the both sides of the ManyToMany relationship.
That means that you would need to do the following:
List<Course> test = myUser.getCourse();
Course course = facade.find(1l);
course.getUsers().add(myUser);
test.add(course);
myUser.setCourse(test);
userFacade.edit(myUser);
When you query for the Course you do not get the user list because you only have Cascade.MERGE set up on that relationship. This means that you need to set it manually as above.

Related

Spring Data Jpa OneToMany save bidirectional

I have a problem with saving child entities.
Here is my example. My model classes look like this:
#Entity
public class ImportDocument {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
private boolean imported;
#Transient
private Status status;
#Basic
private char statusValue;
#OneToMany(mappedBy = "importDocument" , cascade = {CascadeType.ALL})
private List<ImportDocumentItem> importDocumentItems;
}
#Entity
public class ImportDocumentItem {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "import_document_id")
#JsonIgnore
private ImportDocument importDocument;
}
I have implemented JpaRepository interfaces for both domain classes.
I try to save with:
importDocumentRepository.save(importDocument);
When I save ImportDocument object, everything is inserted. But the problem is that, the import_document_item.import_document_id (which is foreign key of import_document_id) attribute is filled with null value, not with id of import_document that I expected. How can I fix this issue?
Thanks a lot.
You have to set entity relations on both side before saving. Here an example
ImportDocument importDocument = new ImportDocument();
//...
importDocument.setImportDocumentItems(items);
items.forEach(ImportDocumentItem::setImportDocument);
importDocumentRepository.save(importDocument);

How to fetch entities by objects value in JPA criteria api query

I am using JPA with JSF datatable with lazy loading.
Here One car can be owned by many users. So when i logged in to the application i want the cars which is owned by the user logged in(assume it as userId=1).
I have a mapping table "Cars_User" that contains carId and userId columns.
My Entities are like this
My Car Class
#Entity
#Table(name="car")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
#Transient
private boolean myCar;
#NotNull
#Size(min = 1, max = 50)
public String name;
#OneToMany(cascade = { CascadeType.REFRESH }, fetch = FetchType.LAZY, orphanRemoval = true)
#JoinTable(name = "Cars_User", joinColumns = #JoinColumn(name = "carId"), inverseJoinColumns = #JoinColumn(name = "userId"))
private List<User> carUsers = new ArrayList<User>();
getters ...
setters ...
}
User Class
#Entity(name = "User")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String firstName;
private String lastName;
}
I have found one answer for Lists of String collection in this link but how can be achieved in my case.
I wanted to do get all Cars entities in criteria api that contains the logged in user id "userId" in carUsers Lists. can anyone please help?
I found the solution. I have passed the logged in user Object "user" in isMember function. This may help for somebody.
CriteriaBuilder criteriaBuilder = em.getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<Car> criteria = criteriaBuilder.createQuery(Car.class);
Root<Car> root = criteria.from(Car.class);
criteria.where(criteriaBuilder.isMember(user, root.get(Car_.carUsers)));
List<Car> cars = em.createQuery(criteria).getResultList();

JPA query method to find by elements in a List?

I have the following two entities (Contact and Participation, linked by a ManyToMany relation) :
#Entity
public class Contact {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(nullable=false)
private String firstName;
#Column(nullable=false)
private String lastName;
#ManyToOne
private Company company;
#ManyToMany(fetch=FetchType.EAGER)
private List<Participation> participations;
}
#Entity
public class Participation {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#ManyToOne
private Company company;
private Status status;
}
I can't figure out how to get Contacts who have a specific Participation in their list. Should I look via Contacts with a specific JPA repository method (findBy...) ? Or would i have to look via the table which was created with both Contact and Participation IDs (ManyToMany) ?
Thanks!

EJB JPA QL. Need query to get data from DB by element in Collection object

I am facing a proble that put me in difficult situation.
I have class Article:
#Entity
#Table(name = "Articles")
public class Article implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="article_id")
private Long id;
#Column(name="a_name")
private String name;
#Column(name="a_content")
private String content;
#OneToMany
#Column(name="a_tag")
private Collection <Tags> tag;
#Entity
#Table(name = "Tags")
public class Tags implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="tag_id")
private Long tag_id;
#Column(name="tag_name",nullable=false)
private String tag_name;
#Column(name="tag_descr")
private String tag_descr;
//position 0 - supertag
//position 1 - subsupertag
//position 2 - subtags
//Collection limited to 3 elements.(3 tags at most, necessaryly Super,subsuper,subtag
#Column(name="super_tags")
#OneToMany
private Collection<Tags> supertags = new ArrayList<Tags>(3);
//0-supertag 1-subsupertag 2- subtags
#Column(name="tag_type")
private int tag_type;
My tagging system is such that I have Supertag, subsuprttag and subtag. Supertag is parent for subsupertag and subtag, subsupertag is parent for subtag.
Each article has super, subsuper and sub tags.
Now, I want to get only articles from database, that has a certain tag, but have no idea how to refere to , for example, element 2 in Collection tags (by name or position), (which would be subtag).
final String q = "SELECT f FROM Article f WHERE f.a_tag= ..I m lost here ...
EntityManager em;
em.createQuery(q).getResultList();
I hope my question is clear enough. I gave it my best shot)) Thank you.
You can join to the tags to access them in JPQL,
see,
http://en.wikibooks.org/wiki/Java_Persistence/JPQL#JOIN
As for the type of Tag, how is the type stored in the database?

JPA Many to One relationship

I am bit beginner on JPA and need some help on fetching the Many to One relationship in JPA.
I have below entities.
User which stores all user information . User extends Audiatable abstract class which is for holding auidt paramters like last modified date, creation date etc.
I am trying to add another fields as lastUpdatedByUser which should get fetched from lastUpdatedBy for which I amtrying to add Many-One relationship.
But the relation is not working somehow, am I doing something wrong here?
AuditableEntity.java
public abstract class AuditableEntity<T extends Entity<T, ID>, ID> implements Auditable {
private static final long serialVersionUID = 1L;
#Column(name = "cruserid")
private Long createdBy;
#Column(name = "crdate")
#Type(type = JpaConstants.TYPE_LOCAL_DATE_TIME)
private LocalDateTime createdOn;
#Column(name = "chuserid")
private Long lastUpdatedBy;
#Column(name = "chdate")
#Type(type = JpaConstants.TYPE_LOCAL_DATE_TIME)
private LocalDateTime lastUpdatedOn;
#Transient
#ManyToOne(fetch = FetchType.LAZY, targetEntity = User.class)
#JoinColumn(name = "usrId", referencedColumnName = "chuserid")
private User lastUpdatedByUser;
User.java
public class User extends AuditableEntity<User, Long> {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "usrId")
private Long id;
#Column(name = "usrName")
private String name;
#Column(name = "loginame")
private String loginName;
}
Well, you marked the association with #Transient, which means that the field is not persistent and should be ignored by JPA.
And you also seem to have two different fields to store the same information: lastUpdatedBy and lastUpdateByUser. Remove the first one, and map the second one as
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "chuserid")
private User lastUpdatedByUser;
This tells that the association is a ManyToOne to the User entity (no need to specify the targetEntity since it's the type of the field), and that this association is materialized by the join column named "chuserid", in the auditable entity's table, and referencing the ID of the User entity (referencedColumnName is only useful when you use composite IDs, or when you reference an entity by a column which is the the ID)