I have been looking the forums and everywhere for a unidirectional manyToMany query. I find many examples but i can't really adjust them to my needs :(
I have 2 entity classes (Anime & User)
Anime {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "anime_id")
private Integer id;
//Other fields etc.
}
User {
#Id
#ValidUsername
#Column(name = "user_id")
private String username;
#ManyToMany()
#JoinTable(name = "users_animes",
joinColumns = #JoinColumn(name = "anime_id", referencedColumnName = "anime_id"),
inverseJoinColumns = #JoinColumn(name = "user_id", referencedColumnName = "user_id"))
private final List<Anime> animes = new ArrayList<>();
}
Anime simply holds the data from the anime.
User holds the username etc of the user and a list of anime that he subscribed to.
Now i'm trying to find a query that will let me get all the animes in that list.
It's mapped in a table as "users_animes".
Would be a huge help since i'm fairly new to JPQL.
Thanks!
Here's a simple example. Let's assume that we have Country Entity, which can have multiple Citizens:
#Entity
#Table (name = "countries")
public class Country implements Serializable {
#Id
#Column (name = "coun_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column (name = "country_name")
private String countryName;
#ManyToMany (cascade = CascadeType.ALL)
#JoinTable (
name = "citizen_country",
joinColumns = #JoinColumn (name = "country_id", referencedColumnName = "coun_id"),
inverseJoinColumns = #JoinColumn (name = "citizen_id", referencedColumnName = "cit_id")
)
private List<Citizen> citizens;
public Country() {}
public Country(String countryName) {
this.countryName = countryName;
}
//getters and setters
}
And Citizen, which can belong to multiple Countries:
#Entity
#Table (name = "citizens")
public class Citizen implements Serializable {
#Id
#Column (name = "cit_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column (name = "country_name")
private String citizenName;
public Citizen() {}
public Citizen(String citizenName) {
this.citizenName = citizenName;
}
public void setId(Long id) { this.id = id; }
public Long getId() { return id; }
public void setCitizenName(String citizenName) { this.citizenName = citizenName; }
public String getCitizenName() { return citizenName; }
//getters and setters
}
It's unidirectional, just as you wanted it to be. Therefore, Citizen Entity is unaware of Country, so you can't get directly information to which Country a certain Citizen belongs. However, you can retrieve info about which Citizens belong to a certain Country.
Going further, you can populate your tables:
Citizen citizen1 = new Citizen("Smith");
Citizen citizen2 = new Citizen("Kowalski");
Citizen citizen3 = new Citizen("Muller");
dataAccess.saveCitizen(citizen1);
dataAccess.saveCitizen(citizen2);
dataAccess.saveCitizen(citizen3);
// now let's fetch them from DB, along with their other properties (only id in this case)
citizen1 = dataAccess.getCitizenByName("Smith");
citizen2 = dataAccess.getCitizenByName("Kowalski");
citizen3 = dataAccess.getCitizenByName("Muller");
Country country1 = new Country("Foo");
Country country2 = new Country("Bar");
// create lists to hold citizens for each country
List<Citizen> citizenList1 = new ArrayList();
List<Citizen> citizenList2 = new ArrayList();
// add elements to the lists
citizenList1.add(citizen1);
citizenList1.add(citizen2);
citizenList2.add(citizen2);
citizenList2.add(citizen3);
//assign lists of citizens to each country
country1.setCitizens(citizenList1);
country2.setCitizens(citizenList2);
//save data in DB
dataAccess.saveCountry(country1);
dataAccess.saveCountry(country2);
//fetch list of all persisted countries (associated Citizens will come along)
countries = dataAccess.getAllCountries();
And finally:
#Stateless
public class DataAccess {
#PersistenceContext
EntityManager em;
public void saveCountry(Country country) {
em.persist(country);
}
public void saveCitizen(Citizen citizen) {
em.persist(citizen);
}
public Citizen getCitizenByName(String name) {
Query query = em.createQuery("SELECT c FROM Citizen c WHERE c.citizenName = :name");
query.setParameter("name", name);
return (Citizen) query.getSingleResult();
}
public List<Country> getAllCountries() {
Query query = em.createQuery("SELECT c FROM Country c");
return (List<Country>) query.getResultList();
}
}
Related
(Not sure if title is fitting for my problem, please correct me if necessary)
I have a controller with a postmapping:
#PostMapping("/user")
ResponseEntity addUser(Users receivedUser, OauthGatewayUser oauthGatewayUser) {
Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
logger.info("POST-Request from user: " + oauthGatewayUser.toString());
logger.info("PostMapping: Received User: " + receivedUser);
userService.addUser(oauthGatewayUser, receivedUser);
return new ResponseEntity(receivedUser, HttpStatus.OK);
}
And I have a users class which can have multiple Islands assigned, so the classes look like this:
#Entity
#Table
public class Users {
#Id
#NonNull
#Column(unique = true)
private String id;
#Column(unique = true)
private String userHandle;
private PrivacyLevel privacyLevelProfile;
private boolean isBlocked;
private Long lastActiveIslandID;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Island> islands = new ArrayList<>();
public Users(String id) {
lastActiveIslandID = 0L;
this.id = id;
privacyLevelProfile = PrivacyLevel.PUBLIC;
}
public Users(String id, String userHandle) {
lastActiveIslandID = 0L;
this.id = id;
this.userHandle = userHandle;
privacyLevelProfile = PrivacyLevel.PUBLIC;
}
public Users() {
}
//Getters and Setters here
}
Island class:
#Entity
#Table
public class Island {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long islandIdOnDevice;
private String name;
private String islandFruit;
public Island(String name, String userID) {
this.name = name;
this.userID = userID;
}
}
public Island() {
}
//Getters and Setters
}
If I now send this as POST-request:
{"id":"baf539b0","islands":[{"islandIdOnDevice":0,"name":"test","fruit":"avocado","userID":"baf539b0"}]}
Then the spring controller logs:
INFO 11916 --- [.83-8083-exec-3] global: POST-Request from user: OauthGatewayUser { id = baf539b0, name = TestUser }
INFO 11916 --- [.83-8083-exec-3] global: PostMapping: Received User: user{id=baf539b0, name='', isBlocked=false, [], last active=null}
What I want is to receive the island as part of the user so I then can attach it in the user service.
The one-to-many annotation specifies an association. It helps spring understand what to do with the collection. But it doesn't 'join' you data in any way when you query it.
Try this:
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn( name = "id", referencedColumnName = "userId")
private List<Island> islands = new ArrayList<>();
I have a User table and a Book table that I would like to connect.
So I created third table Borrow that has foreign key (book_id, user_id) and takenDate and broughtDate fields.
User.java
#Entity
#Table(name = "Users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String surname;
private String username;
private String email;
private String password;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Borrow> borrow;
....
Book.java
#Entity
#Table(name = "Books")
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String title;
private String ISBN;
private String author;
private String issuer;
private Integer dateOfIssue;
private Boolean IsRented;
#OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Borrow> borrow;
.....
Borrow.java
#Entity
#Table(name = "Borrows")
#IdClass(BorrowId.class)
public class Borrow {
private Date takenDate;
private Date broughtDate;
//lazy means it will get details of book
// only if we call GET method
#Id
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "book_id", referencedColumnName = "id")
private Book book;
#Id
#JsonIgnore
#ManyToOne
#JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
....
BorowId.java
public class BorrowId implements Serializable {
private int book;
private int user;
// getters/setters and most importantly equals() and hashCode()
public int getBook() {
return book;
}
public void setBook(int book) {
this.book = book;
}
public int getUser() {
return user;
}
public void setUser(int user) {
this.user = user;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BorrowId)) return false;
BorrowId borrowId = (BorrowId) o;
return getBook() == borrowId.getBook() &&
getUser() == borrowId.getUser();
}
#Override
public int hashCode() {
return Objects.hash(getBook(), getUser());
}
}
My MySql database design looks like this:
I am trying to add data to Borrow table something like this:
EDITED
#Transactional
#PostMapping("/addUser/{id}/borrow")
public ResponseEntity<Object> createItem(#PathVariable int id, #RequestBody Borrow borrow, #RequestBody Book book){
Optional<User> userOptional = userRepository.findById(id);
Optional<Book> bookOptional = bookRepository.findById(book.getId());
if(!userOptional.isPresent()){
throw new UserNotFoundException("id-" + id);
}
User user = userOptional.get();
borrow.setUser(user);
borrow.setBook(book);
borrowRepository.save(borrow);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(borrow.getId()).toUri();
return ResponseEntity.created(location).build();
}
I have't finished it because I am not sure how :/
Any tip is appreciated!
You are almost there. You just have to keep in mind two things:
1) You have to fetch the Book via repository as well (you only fetch the User currently)
2) All three operation have to be within the same transactional context:
fetching of `User`, fetching of `Book` and save `Borrow` entity.
TIP: You can put all these inside a Service and mark it as #Transactional or mark the #Post method as #Transactional. I would suggest first option, but it is up to you.
EDIT:
Optional<Book> bookOptional = bookRepository.findById(book.getId());
Also, it seems adequate to use #EmbeddedId instead of #IdClass here as ids are actual foreign entities:
#Embeddable
public class BorrowId{
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "book_id", referencedColumnName = "id")
private Book book;
#ManyToOne
#JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
}
and then in the Borrow class:
#Entity class Borrow{
#EmbeddedId BorrwId borrowId;
...
}
and in the Post method:
BorrowId borrowId = new BorrowId();
borrowId.setUser(user);
borrowId.setBook(book);
borrow.setBorrowId(borrowId);
borrowRepository.save(borrow);
Apologies if there is an obvious problem, I'm new to Hibernate. I've spent the last 3 hours scouring the googles, it's very likely I'm not phrasing my question correctly. I think I might have a circular reference, but I'm not sure.
I have 3 entities. The relationships I am trying to materialize are:
An Institution can have many courses
An Institution can be a sponsor
A course can have many sponsors
A sponsor can have many courses
My unit test creates these entities, saves them, and then queries for them to make sure I can read & write to the DB correctly and maintain the relationships.
If I only add an institution (BMC) to a course, everything is fine.
If I only add sponsors (BMC, HKU) to a course, everything is fine.
If I add an institution (BMC) and sponsors (BMC) to a course, when I try to get the course back, I get an empty object, which ultimately causes an NPE
I'm representing the many-to-many relationship in the third entity, CourseDetails. Ultimately, the CourseDetails will have several many-to-many relationships. However, only institution is used in multiple places.
Any help would be greatly appreciated.
** EDIT ** I can confirm that the data is being saved correctly in the database when I look at in Toad. The course table has the correct institution_id and the courseDetails_institution has the correct mapping of course_id and institution_id
Institution
#Entity
#Table(name="institution")
public class Institution {
#Id
#GeneratedValue(strategy = GenerationType.TABLE, generator="table-generator")
#TableGenerator(name = "table-generator", pkColumnValue = "institution_id")
#Column(name = "institution_id")
private int id;
#Column(name = "sponsor")
private boolean sponsor;
#ManyToMany(mappedBy = "sponsors", fetch = FetchType.EAGER)
protected Set<CourseDetails> courseDetails = new HashSet<>();
#OneToMany(mappedBy = "institution")
#Cascade({CascadeType.SAVE_UPDATE})
protected Set<Course> courses = new HashSet<>();
protected Institution() {
// no-op constructor for hibernate, cannot be private
}
public Institution(String name, String abbreviation) {
super(name, abbreviation);
this.sponsor = false;
}
// Setters, getters, equals, hashcode omitted for brevity.
Course
#Entity
#Table(name = "course")
public class Course {
#Id
#GeneratedValue(strategy = GenerationType.TABLE, generator="table-generator")
#TableGenerator(name = "table-generator", pkColumnValue = "course_id")
#Column(name = "course_id")
private int id;
#ManyToOne
private Institution institution;
#ManyToMany(mappedBy = "courses", fetch = FetchType.EAGER)
protected Set<CourseDetails> courseDetails = new HashSet<>();
// Setters, getters, equals, hashcode omitted for brevity.
CourseDetails
#Entity
#Table(name="courseDetails")
public class CourseDetails {
#Id
#GeneratedValue(strategy = GenerationType.TABLE, generator = "table-generator")
#TableGenerator(name = "table-generator", pkColumnValue = "courseDetails_id")
#Column(name = "courseDetails_id")
private int id;
#ManyToMany(fetch = FetchType.LAZY)
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
protected Set<Course> courses = new HashSet<>();
#ManyToMany(fetch = FetchType.LAZY)
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
protected Set<Institution> sponsors = new HashSet<>();
// Setters, getters, equals, hashcode omitted for brevity.
Relevant methods for querying
public <T> List getAllEntities(final Class<T> clazz) {
CriteriaBuilder builder = sessionFactory.getCriteriaBuilder();
CriteriaQuery<T> criteria = builder.createQuery(clazz);
Root<T> root = criteria.from(clazz);
criteria.select(root);
final Session session = startTransaction();
List<T> results = session.createQuery(criteria).getResultList();
endTransaction(session);
return results;
}
public Session startTransaction() {
Session session = sessionFactory.openSession();
session.beginTransaction();
activeSessions.add(session);
return session;
}
public void endTransaction(final Session session) {
session.getTransaction().commit();
session.close();
activeSessions.remove(session);
}
Jules' comments have answered my question. I needed to either have the institution be a many-to-many relationship or create two entities that map to the same table. This is what I ended up doing:
BaseInstitution
#Entity
#Table(name="institution")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorFormula(
"CASE WHEN sponsor " +
"THEN 'SPONSOR' " +
"ELSE 'INSTITUTION' " +
"END "
)
public class BaseInstitution {
#Id
#GeneratedValue(strategy = GenerationType.TABLE, generator="table-generator")
#TableGenerator(name = "table-generator", pkColumnValue = "institution_id")
#Column(name = "institution_id")
private int id;
#Column(name = "sponsor")
private boolean sponsor = false;
Sponsor
#Entity
#DiscriminatorValue("SPONSOR")
public class Sponsor extends BaseInstitution {
#ManyToMany(mappedBy = "sponsors", fetch = FetchType.EAGER)
protected Set<CourseDetails> courseDetails = new HashSet<>();
Institution
#Entity
#DiscriminatorValue("INSTITUTION")
public class Institution extends BaseInstitution {
#OneToMany(mappedBy = "institution")
#Cascade({CascadeType.SAVE_UPDATE})
protected Set<Course> courses = new HashSet<>();
Course
#Entity
#Table(name = "course")
public class Course {
#Id
#GeneratedValue(strategy = GenerationType.TABLE, generator="table-generator")
#TableGenerator(name = "table-generator", pkColumnValue = "course_id")
#Column(name = "course_id")
private int id;
#ManyToOne
#Cascade({CascadeType.SAVE_UPDATE})
private Institution institution;
#ManyToMany(mappedBy = "courses", fetch = FetchType.EAGER)
protected Set<CourseDetails> courseDetails = new HashSet<>();
CourseDetails
#Entity
#Table(name="courseDetails")
public class CourseDetails {
#Id
#GeneratedValue(strategy = GenerationType.TABLE, generator = "table-generator")
#TableGenerator(name = "table-generator", pkColumnValue = "courseDetails_id")
#Column(name = "courseDetails_id")
private int id;
#ManyToMany(fetch = FetchType.LAZY)
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
protected Set<Course> courses = new HashSet<>();
#ManyToMany(fetch = FetchType.EAGER)
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
protected Set<Sponsor> sponsors = new HashSet<>();
I'm facing a difficulty in developing a server in Spring (+ Hibernate + JPA) for a project.
The structure of the server (the part of interest in this case) is composed of catalogs composed of products that can have some related feedbacks.
Here I share the 3 entities:
Catalog.java
#Entity
#Data
#Table(name = "catalog")
public class Catalog {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false, unique = true)
private String name;
private String description;
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = "catalog_user_id", nullable = false)
private User user;
#ManyToMany(cascade = {CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinTable(name = "catalog_product",
joinColumns = {#JoinColumn(name = "catalog_id")},
inverseJoinColumns = {#JoinColumn(name = "product_id")}
)
private List<Product> products;
public Catalog() {}
}
Product.java
#Entity
#Data
#Table(name = "product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false, unique = true)
private String name;
private String description;
#Column(nullable = false, length = 1)
#MapKeyEnumerated(EnumType.ORDINAL)
private Category category;
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = "product_user_id", nullable = false)
private User user;
public Product() {}
}
Feedback.java
#Entity
#Data
#Table(name = "feedback")
public class Feedback {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = "feedback_user_id", nullable = false)
private User user;
#Column(nullable = false, length = 1)
#MapKeyEnumerated(EnumType.ORDINAL)
private Rating rating;
private String text;
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = "product_id", nullable = false)
private Product product;
public Feedback() {}
}
The problem occurs when I try to delete some entities. What I want is:
when I delete a catalog also the catalog references in the "catalog_product" join table should be deleted (but the product linked with the catalog should not be deleted);
when I delete a product also the product references in the "catalog_product" join table and the feedbacks related to that product should be deleted;
when I delete a feedback nothing happens.
In the business layer I have this operations:
CatalogServiceImpl.java
#Service
public class CatalogServiceImpl implements CatalogService {
#Autowired
private CatalogDAO catalogDAO;
#Autowired
private ModelMapper mapper;
public CatalogDTO findById(Long id) {
Catalog catalog = catalogDAO.findById(id);
return mapper.map(catalog, CatalogDTO.class);
}
public CatalogDTO findByName(String name) {
Catalog catalog = catalogDAO.findByName(name);
return mapper.map(catalog, CatalogDTO.class);
}
public List<CatalogDTO> findByUserId(Long id) {
List<Catalog> catalogs = catalogDAO.findByUserId(id);
Type listCatalogsType = new TypeToken<List<CatalogDTO>>() {}.getType();
return mapper.map(catalogs, listCatalogsType);
}
public List<CatalogDTO> findAll() {
List<Catalog> catalogs = catalogDAO.findAll();
Type listCatalogsType = new TypeToken<List<CatalogDTO>>() {}.getType();
return mapper.map(catalogs, listCatalogsType);
}
public CatalogDTO createCatalog(CatalogDTO catalogDTO) {
Catalog catalog = mapper.map(catalogDTO, Catalog.class);
Catalog catalogFromDB = catalogDAO.save(catalog);
return mapper.map(catalogFromDB, CatalogDTO.class);
}
public CatalogDTO updateCatalog(CatalogDTO catalogDTO) {
Catalog catalog = mapper.map(catalogDTO, Catalog.class);
Catalog catalogFromDB;
if(catalogDAO.exists(catalog.getId())) {
catalogFromDB = catalogDAO.save(catalog);
} else {
catalogFromDB = null;
}
return mapper.map(catalogFromDB, CatalogDTO.class);
}
public void deleteCatalog(Long id) {
Catalog catalog = catalogDAO.findById(id);
if(catalog != null) {
catalogDAO.delete(catalog.getId());
}
}
}
ProductServiceImpl.java
#Service
public class ProductServiceImpl implements ProductService {
#Autowired
private ProductDAO productDAO;
#Autowired
private ModelMapper mapper;
public ProductDTO findById(Long id) {
Product product = productDAO.findById(id);
return mapper.map(product, ProductDTO.class);
}
public ProductDTO findByName(String name) {
Product product = productDAO.findByName(name);
return mapper.map(product, ProductDTO.class);
}
public ProductDTO findByCategory(Category category) {
Product product = productDAO.findByCategory(category);
return mapper.map(product, ProductDTO.class);
}
public List<ProductDTO> findByUserId(Long id) {
List<Product> products = productDAO.findByUserId(id);
Type listProductsType = new TypeToken<List<ProductDTO>>() {}.getType();
return mapper.map(products, listProductsType);
}
public List<ProductDTO> findAll() {
List<Product> products = productDAO.findAll();
Type listProductsType = new TypeToken<List<ProductDTO>>() {}.getType();
return mapper.map(products, listProductsType);
}
public ProductDTO createProduct(ProductDTO productDTO) {
Product product = mapper.map(productDTO, Product.class);
Product productFromDB = productDAO.save(product);
return mapper.map(productFromDB, ProductDTO.class);
}
public ProductDTO updateProduct(ProductDTO productDTO) {
Product product = mapper.map(productDTO, Product.class);
Product productFromDB;
if(productDAO.exists(product.getId())) {
System.out.println(product.toString());
productFromDB = productDAO.save(product);
} else {
productFromDB = null;
}
return mapper.map(productFromDB, ProductDTO.class);
}
public void deleteProduct(Long id) {
Product product = productDAO.findById(id);
if(product != null) {
productDAO.delete(product.getId());
}
}
}
Now, when I try performing the operations of deletion of catalog or product an error of constraint key fail is triggered. For example trying to delete a product which has a reference in the catalog_product join table:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`e01`.`catalog_product`, CONSTRAINT `FKdx5j7bcx77t7h0hjw6tvoxmp1` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`))
I don't understand if there's a way to set the relations between entities to make what I want in an automatic way with Spring, or if I have to remove records with reference manually before the deletion of the catalog/product.
Thanks a lot in advance to everyone!
Luca
I need to create a join table in my database using JPA annotations so the result will be this:
So far I just implemented 2 entities:
#Entity
#Table(name="USERS", schema="ADMIN")
public class User implements Serializable {
private static final long serialVersionUID = -1244856316278032177L;
#Id
#Column(nullable = false)
private String userid;
#Column(nullable = false)
private String password;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
#Entity
#Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {
private static final long serialVersionUID = -7274308564659753174L;
#Id
#Column(nullable = false)
private String groupid;
public String getGroupid() {
return groupid;
}
public void setGroupid(String groupid) {
this.groupid = groupid;
}
}
Should i create another entity called USER_GROUP or i can just add some annotations, so the join table will be created automatically when i run create tables from entities(ORM)?
How should i annotate my entities to achieve the same as in the image?
You definitely shouldn't create User_Group entity as it's more the underlying database representation than the object oriented one.
You can achieve the join table by defining something like:
#Entity
#Table(name="USERS", schema="ADMIN")
public class User implements Serializable {
//...
#ManyToOne
#JoinTable(name="USER_GROUP")
Group group;
#Entity
#Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {
//...
#OneToMany(mappedBy="group")
Set<User> users;
Edit: If you want to explicitly set the names of the columns you could use #JoinColumn elements as shown below:
#ManyToOne
#JoinTable(name="USER_GROUP",
joinColumns = #JoinColumn(name = "userid",
referencedColumnName = "userid"),
inverseJoinColumns = #JoinColumn(name = "groupid",
referencedColumnName = "groupid"))
Group group;
I would implement it this way:
#Entity
#Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {
#OneToMany
#JoinTable(name = "USER_GROUP",
joinColumns = #JoinColumn(name = "groupid"),
inverseJoinColumns = #JoinColumn(name = "userid"))
private List<User> users;
}
Solution suggested by #PedroKowalski should work too, but then you'll have to keep a reference to Group entity in your User entity which is not always possible.
To have the same annotations like in your diagram you can do this in your User class:
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "USER_GROUP",
joinColumns = { #JoinColumn(name = "userid") },
inverseJoinColumns = { #JoinColumn(name = "groupid") })
private List<Group> grups;
in your group class
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "USER_GROUP",
joinColumns = { #JoinColumn(name = "groupid") },
inverseJoinColumns = { #JoinColumn(name = "userid") })
private List<User> users;
I'm wondering what is the point to create a Join Table in this way, considering that we can't access directly for queries?
JPA doesn't allow to make queries directly to the Join Table, so if the user want to do an operation on USER_GROUP, he has to creare a normal join query between users and groups; due to this, the join table USER_GROUP is useless.