I need to add two extra columns (Status, createdby) in Users_Reports table.which has many to many relationship with Users and Reports tables.
TABLE STRUCTURE OF Users TABLE.
#Entity
#Table(name="Users")
#DynamicUpdate
#DynamicInsert
public class DBUsers {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID", updatable = false, insertable = false)
private int ID;
#Column(name="code", length=20)
private String code;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "Users_Reports",
joinColumns = {
#JoinColumn(name = "ID")},
inverseJoinColumns = {
#JoinColumn(name = "reportid")})
public List<DBReports> dBReports;
}
TABLE STRUCTURE OF Reports TABLE
#Entity
#Table(name="Reports")
public class DBReports{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="REPORTID")
private int reportid;
#Column(name="REPORTDATA", length=200)
private String reportdata;
#ManyToMany(mappedBy="dBReports",fetch = FetchType.LAZY)
private List<DBUsers> dBUsers;
}
Related
I created two simple entities for trying out the java persistence manytomany mapping. But whatever I try, the jointable won't be populated with a mapping and remains empty.
UserClass:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
#ManyToMany(targetEntity = Order.class ,fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "users_orders",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "order_id", referencedColumnName = "id")
)
#JsonIgnoreProperties(value = "orderUsers")
private Set<Order> userOrders = new HashSet<>();
}
OrderClass:
#Entity
#Table(name = "orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
#ManyToMany(mappedBy = "userOrders", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JsonIgnoreProperties(value = "userOrders")
private Set<User> orderUsers = new HashSet<>();
}
I added Getter/Setter/Constructor via Lombok.
Create and save an user. Create an order, add the user and save it. But still the jointable remains empty.
Any ideas?
I have an issue with hibernate and postgres using spring boot.
When I run the application I see in postgres logs these errors(without any data bootstrap):
2021-06-25 13:55:31.057 UTC [81] ERROR: constraint "uk_j1xiaxeat9b5r1qs27ei0t2a6" of
relation "process_template_base_environmental_impact" does not exist
2021-06-25 13:55:31.057 UTC [81] STATEMENT: alter table
process_template_base_environmental_impact drop constraint
UK_j1xiaxeat9b5r1qs27ei0t2a6
2021-06-25 13:55:31.062 UTC [81] ERROR: constraint "uk_9568qjc94suvuskoi9o2li3er" of
relation "process_template_elementary_flow_template" does not exist
2021-06-25 13:55:31.062 UTC [81] STATEMENT: alter table
process_template_elementary_flow_template drop constraint
UK_9568qjc94suvuskoi9o2li3er
2021-06-25 13:55:31.064 UTC [81] ERROR: constraint "uk_dy1ej2j9qxeoq6ca641tpfxr5" of
relation "process_template_flow_template" does not exist
2021-06-25 13:55:31.064 UTC [81] STATEMENT: alter table
process_template_flow_template drop constraint UK_dy1ej2j9qxeoq6ca641tpfxr5
I have an entity called ProcessTemplate with ProcessTemplateId as compositeKey, and 3 cascades on ElementaryFlowTemplate, BaseEnvironmentalImpact, and FlowTemplate.
ProcessTemplate:
#Data
#Entity
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Table(name = "process_template")
public class ProcessTemplate {
#EmbeddedId
#EqualsAndHashCode.Include
private ProcessTemplateId id;
#ManyToOne
#JoinColumn(name = "fk_process_base", referencedColumnName = "id")
private ProcessBase processBase;
#ManyToOne
#JoinColumn(name = "fk_reference_flow_base", referencedColumnName = "id")
private FlowBase referenceProduct;
#OneToMany(cascade = CascadeType.ALL)
private Set<BaseEnvironmentalImpact> baseEnvironmentalImpacts;
#OneToMany(cascade = CascadeType.ALL)
#OrderBy("impactsContribute DESC" )
private Set<FlowTemplate> flowsTemplate;
#OneToMany(cascade = CascadeType.ALL)
#OrderBy("impactsContribute DESC" )
private Set<ElementaryFlowTemplate> elementaryFlowsTemplate;
#ManyToOne
#JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;
#Column(name = "version")
#Version
private Long version;
}
ProcessTemplateId:
#Embeddable
public class ProcessTemplateId implements Serializable {
#Column(name = "process_base_id")
private UUID processBaseId;
#Column(name = "reference_product_id")
private UUID referenceProductId;
public ProcessTemplateId() {
}
public ProcessTemplateId(UUID processBaseId, UUID referenceProductId) {
this.processBaseId = processBaseId;
this.referenceProductId = referenceProductId;
}
public UUID getProcessBaseId() {
return processBaseId;
}
public UUID getReferenceProductId() {
return referenceProductId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ProcessTemplateId)) return false;
ProcessTemplateId that = (ProcessTemplateId) o;
return Objects.equals(getProcessBaseId(), that.getProcessBaseId()) &&
Objects.equals(getReferenceProductId(), that.getReferenceProductId());
}
#Override
public int hashCode() {
return Objects.hash(getProcessBaseId(), getReferenceProductId());
}
}
AbstractFlowTemplate:
#Data
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractFlowTemplate {
#Id
#EqualsAndHashCode.Include
private String id;
#Enumerated(EnumType.STRING)
private FlowType flowType;
#ManyToOne
#JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;
#Column(name = "version")
#Version
private Long version;
}
ElementaryFlowTemplate:
#Data
#Entity
#EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
#Table(name = "elementary_flow_template")
public class ElementaryFlowTemplate extends AbstractFlowTemplate {
#ManyToOne
#JoinColumn(name = "fk_elementary_flow_base", referencedColumnName = "id")
private ElementaryFlowBase elementaryFlowBase;
}
FlowTemplate (linkedProcessTemplate is not the bidirectional relation to ProcessTemplate but another unidirectional relation, because each flowTemplate had a link to another ProcessTemplate):
#Data
#Entity
#EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
#Table(name = "flow_template")
public class FlowTemplate extends AbstractFlowTemplate {
#ManyToOne
#JoinColumn(name = "fk_flow_base", referencedColumnName = "id")
private FlowBase flowBase;
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumns({#JoinColumn(name = "process_base_id", referencedColumnName =
"process_base_id"),
#JoinColumn(name = "reference_product_id", referencedColumnName =
"reference_product_id")})
private ProcessTemplate linkedProcessTemplate;
}
BaseEnvironmentalImpact:
#Data
#Entity
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Table(name = "base_environmental_impact")
public class BaseEnvironmentalImpact {
#Id
#EqualsAndHashCode.Include
private String id;
private double value;
#ManyToOne
#JoinColumn(name = "fk_methodology", referencedColumnName = "id")
private Methodology methodology;
#ManyToOne
#JoinColumn(name = "fk_impact_category", referencedColumnName = "id")
private ImpactCategory impactCategory;
#ManyToOne
#JoinColumn(name = "fk_impact_indicator", referencedColumnName = "id")
private ImpactIndicator impactIndicator;
#ManyToOne
#JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;
#Column(name = "version")
#Version
private Long version;
//ref
#ManyToOne
#JoinColumn(name = "fk_elementary_flow_base")
private ElementaryFlowBase elementaryFlowBase;
#ManyToOne
#JoinColumns({
#JoinColumn(
name = "process_base_id",
referencedColumnName = "process_base_id"),
#JoinColumn(
name = "reference_product_id",
referencedColumnName = "reference_product_id")
})
private ProcessTemplate processTemplate;
}
As I wrote I cannot understand why I had an errors log, probably I make a mistake in the relation or cascade but I'm not able to figure out the issue. If I import data they seem correctly inserted so I cannot understand the problem.
Thanks in advance for the help.
SOLVED, EDIT:
I solve only the error on ProcessTemplate-BaseEnvironmentalImpact adding a mappedBy.
I don't include a schema because I think it's autogenerated, I include these parameters in application properties:
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation = true
spring.jpa.hibernate.ddl-auto = create-drop
logging.level.org.hibernate = ERROR
spring.jpa.generate-ddl = true
I also solved other issues adding:
#JoinColumns({
#JoinColumn(name = "fk_pt_process_base_id", referencedColumnName = "process_base_id"),
#JoinColumn(name = "fk_pt_reference_product_id", referencedColumnName = "reference_product_id")
} )
I have a problem with DiscriminatorColumn and DiscriminatorValue.
My expectation is :
-TypeOne, TypeTwo, TypeThree are options related to the User.
-A user can have TypeOne only 1 row.
-A user can have TypeTwo or TypeThree multiple rows.
-I used Pageable for search criteria and sorting by typeOneEntity.optionCode
User table.
|id|user_id|
|-|-|
|1114|a#a.com|
UserOption table.
|id|user_id|option_code|option_type_name|
|-|-|-|-|
|1|1114|CODE_1|TYPE_1|
|2|1114|CODE_2|TYPE_2|
|3|1114|CODE_3|TYPE_2|
|4|1114|CODE_4|TYPE_3|
Ps. User.id = UserOption.user_id
I have to create three entities map to this data.
#Entity
#Table(name = "user")
public class User{
#Column()
private Long id;
#Column()
private String userId;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id", referencedColumnName = "user_id", insertable = false, updatable = false)
private TypeOne typeOneEntity;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "id", referencedColumnName = "user_id", insertable = false, updatable = false)
private Set<TypeTwo> typeTwoEntities;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "id", referencedColumnName = "user_id", insertable = false, updatable = false)
private Set<TypeThree> typeThreeEntities;
}
#Table(name = "user_option")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "option_type_name")
public abstract class UserOption{
#Column
private Long id;
#Column(name = "user_id", nullable = false)
private Long userId;
#Column
private String optionCode;
}
#Entity
#DiscriminatorValue(value = "TYPE_1")
public class TypeOne extends UserOption {
}
#Entity
#DiscriminatorValue(value = "TYPE_2")
public class TypeTwo extends UserOption {
}
#Entity
#DiscriminatorValue(value = "TYPE_3")
public class TypeThree extends UserOption {
}
After I build and try to find data, I found two issues.
1.On typeOneEntity(#OneToOne) is null.
2.On #OneToMany : I got this error ORA-01722: invalid number (error message from Hibernate)
This Entity model that I create it correct or not?
Or it need to change entity model.
I have problems to solve this relationship between User and Roles.
I was able to resolve the relations between User-Organization and Organization-Roles
How can I solve it using notations?
EDIT
I have these classes:
Organization Class
#Entity
#Table(name = "Organizations")
public class Organization implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
private String name;
private String imgLogo;
#ManyToMany
#JoinTable(
name = "OrganizationRoles",
joinColumns = {#JoinColumn(name = "organizationId",
referencedColumnName = "id", updatable = false)},
inverseJoinColumns = {#JoinColumn(name = "roleId",
referencedColumnName = "id", updatable = false)}
)
private List<Role> roles;
....
}
User Class
#Entity
#Table(name = "Users")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
private String name;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "organizationId", nullable = false)
private Organization organization;
????????
private List<Role> roles;
...
}
Thank you!
Tables
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