I'm struggling with following issue:
Caused by: org.hibernate.MappingException: Foreign key
(FKj4uw5b6ekvxc2djohvon7lk7:bi_person_country_countries
[person_country_id])) must have same number of columns as the
referenced primary key (bi_person_country [country_id,person_id])
I created 4 models:
#Table(name = "bi_country")
#Entity
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "name")
private String name;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "bi_person_country", joinColumns = #JoinColumn(name = "country_id"), inverseJoinColumns = #JoinColumn(name = "person_id"))
private Set<Person> persons;
Gender:
#Table(name = "bi_gender")
#Entity
public class Gender {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "name")
private String name;
public Integer getId() {
return id;
}
Person:
#Table(name = "bi_person")
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "name")
private String name;
#Column(name = "last_name")
private String lastName;
#Column(name = "additional_info")
private String additionalInfo;
#ManyToMany(cascade = CascadeType.ALL, mappedBy = "persons")
private Set<Country> countries;
#ManyToOne
private Gender gender;
PersonCountry:
#Table(name = "bi_person_country")
#Entity
public class PersonCountry {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne
private Person person;
#ManyToMany
private List<Country> countries;
You dont need the PersonCountry class here as you are using #ManyToMany in both cases being Person and Country mappings.
If you have to keep it for some reason.. the linking table should not contain #OneToMany / #ManyToMany mappings, so you would have:
#ManyToOne
private Person person;
#ManyToOne
private Country country;
Keep in mind you may need to use #JoinColumn also if the database names are different than person_id and country_id.
Related
i am currently building an Application with Spring and i have a Question there:
I want to have an Entity Address which looks like this:
#Entity(name = "Address")
#Table(name = "address")
#EntityListeners(AuditingEntityListener.class)
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "city")
private String city;
#Column(name = "country")
private String country;
#Column(name = "postalcode")
private String postalCode;
#Column(name = "state")
private String state;
#Column(name = "street")
private String street;
public Address() {
}
}
I want to use this Address Entity in multiple Entities, for example in the User or Order Entity. Later, i will like to have many Entities which need an Address. But i don't want to specify each Relation in the Address Entity, otherwise it will get to complex. Is it possible to have a Link from the User to the Address with only specifying this Link in the User Entity?
My User Entity looks something like this:
#Entity(name = "User")
#Table(name = "User")
#EntityListeners(AuditingEntityListener.class)
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "username")
private String userName;
#OneToOne(
mappedBy = "address",
orphanRemoval = true,
cascade = {
CascadeType.PERSIST,
CascadeType.REMOVE
}
)
private Address billingAddress;
public User() {
}
}
Yes, it is possible, but you don't actually need mappedBy property, otherwise you are telling JPA to search for a address property in the other side of the relationship (that you actually want to be unidirectional):
#Entity(name = "User")
#Table(name = "User")
#EntityListeners(AuditingEntityListener.class)
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "username")
private String userName;
#OneToOne(
orphanRemoval = true,
cascade = { CascadeType.PERSIST, CascadeType.REMOVE }
)
private Address billingAddress;
public User() {
}
}
You can read more about this in the following online resources:
https://docs.oracle.com/javaee/6/api/javax/persistence/OneToOne.html
https://www.baeldung.com/jpa-one-to-one
https://javabydeveloper.com/one-one-unidirectional-association/
I am developing application with Spring Boot, Vaadin and JPA.
I created 3 entity classes:
Author:
#Entity
#Table(name = "author")
public class Author {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name = "name")
private String name;
#Column(name = "surname")
private String surname;
#Column(name = "patronymic")
private String patronymic;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Book> books;
Genre:
#Entity(name = "genre")
#Table(name = "genre")
public class Genre {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(fetch = FetchType.LAZY, mappedBy = "genre", cascade = CascadeType.ALL, orphanRemoval = true)
private Book book;
The book is related to the author (many books - one author) and genre (one genre - one book)
Book:
#Entity
#Table(name = "book")
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
#JoinColumn(name = "author_id")
private Author author;
#OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "genre_id")
private Genre genre;
#Column(name = "publisher")
private String publisher;
#Column(name = "year")
private int year;
#Column(name = "city")
private String city;
.. and when I run my spring boot application I get the error.
Caused by: org.hibernate.HibernateException: More than one row with the given identifier was found: 3, for class: com.app.entity.Book
Where did I go wrong?
I have strange problem. I have entity Company, Branch and Address.
Company has list of branch and every branch has address.
Im trying to persist branch with not exist before address entity, but Address is persist with nulls columns.
#Data
#Entity
#Indexed
#Table(name = "company")
public class Company {
#Id
#GeneratedValue(generator = "UUID")
#GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator"
)
private String id;
#Field
#Column(name = "full_name", nullable = false, unique = true)
private String fullName;
#OneToMany(mappedBy = "company")
private Set<Branch> branches;
}
#Data
#Entity
#Table(name = "branch")
public class Branch {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column
private String phone;
#Column
private String email;
#OneToOne(cascade = CascadeType.PERSIST)
#JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
#ManyToOne
#JoinColumn(name = "company_id", referencedColumnName = "id")
private Company company;
}
#Entity
#Table(name = "address")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column
private String street;
#OneToOne(mappedBy = "address")
private Company company;
#OneToOne(mappedBy = "address")
private Branch branch;
}
Service ...
public Integer addBranch(BranchDto branchDto) {
Branch branch = modelMapper.map(branchDto, Branch.class);
Company company = companyRepository.getCompanyById(branchDto.getCompanyId());
branch.setCompany(company);
return branchRepository.save(branch).getId();
}
Dto...
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
public class BranchDto {
private Integer id;
private String phone;
private String email;
private AddressDto address;
private String companyId;
}
And that is effect...
Debugger...
What is the problem? Can you help me ?
You are using 'mappedBy' with the same id, It only works with the first one he find.
Try to change to other id.
I have 2 tables called Product and Category with many-to-many relationship. And Product has a one-to-many relationship with Images table. I created a table Product_Category to link 2 table Product and Category together. My problem is when 1 product belongs to 1 category, it's just fine with 4 images of that product. But if 1 product belongs to 2 categories, i get 8 images instead of 4
This is image of problem
As you can see is's supposed to be _1 _2 _3 _4 instead _1 _1 _2 _2 ...
This is my entities class
ProductEntity
#Entity
#Table(name = "product")
public class ProductEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#Column(name = "description")
private String description;
#Column(name = "price")
private double price;
#Column(name = "material")
private String material;
#ManyToOne
#JoinColumn(name="careId")
private ProductCareEntity productCare;
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER)
private List<ImageEntity> images;
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER)
private List<ProductCategoryEntity> productCategoryEntities;
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER)
private List<OrderDetailEntity> orderDetailEntityList;
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER,cascade=CascadeType.ALL)
private List<ProductSizeQuantityEntity> productSizeQuantities;
CategoryEntity
#Entity
#Table(name = "category")
public class CategoryEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#OneToMany(mappedBy = "category", fetch = FetchType.EAGER)
private List<ProductCategoryEntity> productCategories;
ProductCategoryEntity
#Entity
#Table(name = "product_category")
public class ProductCategoryEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#ManyToOne
#JoinColumn(name = "categoryId")
private CategoryEntity category;
#ManyToOne
#JoinColumn(name = "productId")
private ProductEntity product;
How can i solve this problem?
I don't think you need ProductCategoryEntity at all. All you need to do is to make a List of Category type in product and List of Product type in Category. like this:
#Entity
#Table(name = "product")
public class ProductEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#Column(name = "description")
private String description;
#Column(name = "price")
private double price;
#Column(name = "material")
private String material;
#ManyToOne
#JoinColumn(name="careId")
private ProductCareEntity productCare;
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER)
private List<ImageEntity> images;
#ManyToMany(cascade = { CascadeType.ALL })
#JoinTable(name = "ProductCategory",
joinColumns = { #JoinColumn(name = "category_id") },
inverseJoinColumns = { #JoinColumn(name = "product_id"))
private List<Category> categories;
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER)
private List<OrderDetailEntity> orderDetailEntityList;
#OneToMany(mappedBy = "product", fetch =
FetchType.EAGER,cascade=CascadeType.ALL)
private List<ProductSizeQuantityEntity> productSizeQuantities;
and
#Entity
#Table(name = "category")
public class CategoryEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#ManyToMany(mappedBy = "projects")
#JoinTable(name = "ProductCategory")
private List<Product> products;
I am facing a hibernate problem in updainting the join table in one to many mapping with hibernate. Below are my two entity class and join table entity class.
ArticleCategoryMap.java
#Entity
#Table(name = "ARTICLECATEGORYMAP")
public class ArticleCategoryMap {
private static final long serialVersionUID = -5653708523600543988L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column ( name = "id")
Long id;
#ManyToOne(targetEntity = Article.class, fetch = FetchType.EAGER, optional = true, cascade = CascadeType.PERSIST)
#JoinColumn(name = "ARTICLE_ID", nullable = true, insertable = true, updatable = true)
private Article article;
#ManyToOne(targetEntity = Category.class, fetch = FetchType.EAGER, optional = true, cascade = CascadeType.PERSIST)
#JoinColumn(name = "CATEGORY_ID", nullable = true, insertable = true, updatable = true)
private Category category;
//setter and getter
}
Article.java
#Entity
#Table(name = "ARTICLE")
public class Article {
private long id;
private String title;
private String description;
private String keywords;
private String content;
#Id
#GeneratedValue
#Column(name = "ARTICLE_ID")
public long getId() {
return id;
}
//setter and getter
}
Category.java
#Entity
#Table(name = "CATEGORY")
public class Category {
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
#JoinTable(
name = "ARTICLECATEGORYMAP",
joinColumns = #JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = #JoinColumn(name = "ARTICLE_ID")
)
#CollectionId(
columns = #Column(name="id"),
type=#Type(type="long"),
generator = "sequence"
)
private Collection<Article> articles;
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
public long getId() {
return id;
}
#OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
#JoinTable(
name = "ARTICLECATEGORYMAP",
joinColumns = #JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = #JoinColumn(name = "ARTICLE_ID")
)
#CollectionId(
columns = #Column(name="id"),
type=#Type(type="long"),
generator = "sequence"
)
// setter an getter
}
Now suppose first time I have 2 elements in article table which is mapping to one entry of the category table. so the join table will look something like
Now due to some reason, I want to update the entry where the article entry will map to a new category ID. So the final DB should look like
So My problem Is how can I update this join table.
If you want one to many relationship (1 category have many articles and 1 article to 1 category) you dont need a join table.
The entity classes should look like that:
Category Entity:
Contains a Set of articles:
#Entity
#Table(name = "CATEGORY")
public class Category {
private long id;
private String name;
#OneToMany(mappedBy="category")
private Set<Article> articles;
......
}
Article Entity:
#Entity
#Table(name = "ARTICLE")
public class Article {
#ManyToOne
#JoinColumn(name="id", nullable=false)
private Category category;
private long id;
private String title;
private String description;
private String keywords;
private String content;
.......
}
For more details take a look at hibernate-one-to-many. Hope this helps.
Also move annotation from methods to fields. This:
private long id;
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
public long getId() {
return id;
}
Should be:
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
private long id;
public long getId() {
return id;
}
Many to many relationship:
At your database you have 3 tables:
CATEGORY
ARTICLE
ARTICLECATEGORYMAP (join table)
For many to many relationship entities would be:
Category Entity:
#Entity
#Table(name = "CATEGORY")
public class Category {
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
private long id;
private String name;
#ManyToMany(cascade = { CascadeType.ALL })
#JoinTable(
name = "ARTICLECATEGORYMAP",
joinColumns = { #JoinColumn(name = "CATEGORY_ID") },
inverseJoinColumns = { #JoinColumn(name = "ARTICLE_ID") }
)
Set<Article > articles = new HashSet<>();
.....
}
Article Entity:
#Entity
#Table(name = "ARTICLE")
public class Article {
#Id
#GeneratedValue
#Column(name = "ARTICLE_ID")
private long id;
private String title;
private String description;
private String keywords;
private String content;
#ManyToMany(mappedBy = "articles")
private Set<Category> categories = new HashSet<>();
.......
}
For more info take a look at many-to-many ralationship