jpa entity mapping couple tables - java

I had entity for JSON parsing
#Entity
public class Product{
private int productId;
private String productName;
private BigDecimal productPrice;
private int productVendorId;
private String productVendorName;
private int productCategoryId;
private String productCategoryName;
//getters setters here
created 3 tables in dataBase:
products (product_id, product_name,product_price, product_vendor_id), product_category_id);
vendors(vendor_id, vendor_name); categories (category_id, category_name);
in 1st table product_vendor_id fk -> vendor_id pk in vendors and product_category_id fk -> category_id pk in categories
i tried something like this:
#Entity
#Table(name = "products, schema = "market")
public class Product
#Id
#Column(updatable = false, nullable = false, name = "product_id")
private int Id;
#Column(name = "product_name")
private String productName;
#Column(name = "product_price")
private BigDecimal productPrice;
#Column(name = "product_vendor_id")
private int productVendorId;
#Columnt(table = "vendors", name = "vendor_name")
private String vendor_name;
#Column(name = "product_category_id")
private int productCategoryId;
#Column(table = "categories", name = "category_name")
private String productCategorName;
//getters setters here
received alot of errors: like i have not category_name column in products table etc. this error i received when used
#Table(name = "products", schema = "market" )
#SecondaryTables({#SecondaryTable(name = "vendors", schema = "market"),
#SecondaryTable(name = "categories", schema = "market")})
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product {
....
#JoinColumn(name = "product_vendor_id", referencedColumnName = "vendor_id")
private int productVendorID;
#JoinColumn(table = "vendors", name = "vendor_name")
private String productVendorName;
#JoinColumn(name = "product_category_id", referencedColumnName =
"product_category_id")
private int productCategoryID;
#JoinColumn(table = "categories", name = "category_name")
private String productCategoryName;
exception:
Caused by: org.postgresql.util.PSQLException: ERROR: column
product0_1_.product_id doesn't exist
Hint: There may have been a link to the "product0_.product_id" column
Position: 705
how can i map this entity on 3 tables?
upd: i don't want separate this entity, i need this for deserialize my json object too, just want reuse this entity on different operations.
example of json
{"productID":"1111111","productName":"Cool product","productPrice":"99.99","productVendorName":"Some store","productVendorID":"1337","productCategoryName":"Food","productCategoryID":"1"}

Since there are 3 separate tables, you would want to create three separate entity classes.
Also I'm assuming vendors and category tables will have one to many relation to product.
Try below code:
Product:
#Entity
public class Product {
#Id
private int productId;
private String productName;
private BigDecimal productPrice;
private String productVendorName;
private String productCategoryName;
#ManyToOne
#JoinColumn(name = "productCategoryId")
private Category category;
#ManyToOne
#JoinColumn(name = "productVendorId")
private Vendors vendor;
}
Category:
#Entity
public class Category {
#Id
private Integer categoryId;
private String categoryName;
#OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#NotEmpty
private List<Product> products = new ArrayList<>();
}
Vendors:
#Entity
public class Vendors {
#Id
private int vendorId;
private String vendorName;
#OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#NotEmpty
private List<Product> products = new ArrayList<>();
}
Though, I would recommend using above approach, if you still want to have single entity class and 3 separate table with redudant data then use below:
#Entity
#SecondaryTables({ #SecondaryTable(name = "vendors"), #SecondaryTable(name = "categories") })
public class Product {
#Id
private int productId;
private String productName;
private BigDecimal productPrice;
private String productVendorName;
private String productCategoryName;
#Column(table = "categories")
private Integer categoryId;
#Column(table = "categories")
private String categoryName;
#Column(table = "vendors")
private int vendorId;
#Column(table = "vendors")
private String vendorName;
}
The id column of the main table will be present in all the 3 tables and used for joining them.

Sorry for poor wording of the question, just didn't know how to explane what i wanted.
All what i need just add #transient annotations for fields which i don't have in products table, and separate it like accepted answer was suggested.
#Entity
#Table(name = "products", schema = "store" )
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product {
#Id
#Column(updatable = false, nullable = false, name = "product_id")
private int productId;
#Column(name = "product_name")
private String productName;
#Column(name = "product_price")
private BigDecimal productPrice;
#Transient
private String productVendorName;
#Transient
private String productCategoryName;
#Transient
private int vendorId;
#Transient
private int categoryId;
#ManyToOne
#JoinColumn(name = "product_category_id")
private Category category;
#ManyToOne
#JoinColumn(name = "product_vendor_id")
private Vendor vendor;
}
for vendors table entity
#Entity
#Table(name = "vendors", schema = "store")
public class Vendor {
#Id
#Column(name = "vendor_id")
private int vendorId;
#Column(name = "vendor_name")
private String vendorName;
#OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true)
#NotNull
private List<Product> products = new ArrayList<>();
}
and for categories
#Entity
#Table(name = "categories", schema = "store")
public class Category {
#Id
#Column(name = "category_id")
private Integer categoryId;
#Column(name = "category_name")
private String categoryName;
#OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true)
#NotNull
private List<Product> products = new ArrayList<>();
}
Wanted to leave here full answer on my question, maybe someone will need it later
Just check some problems with toString. Use it only in Product.class and better make 2 versions for print json and jpa.

Related

#JsonIgnoreProperties JPA - Not ignoring properties

I am having a faq entity as below. Here createdBy field is having a manyToOne relationship with the user entity. Below joinColumns shows the association.
In the User entity, i have OneToMany relationship with UserRoles and UsersUnit which is EAGER load for User and not for faq. So i added #JsonIgnoreProperties
for UsersUnit and UsersRole and the corresponding User entity is shown below.
#Entity
#Table(name = "FAQ", catalog="abc")
public class Faq implements Serializable {
public Faq() {
super();
}
#Column(name = "CREATE_DATE")
private Timestamp createDate;
#Where(clause = "DELETE_DATE is null")
#Column(name = "DELETE_DATE")
private Timestamp deleteDate;
#Column(name = "DELETED_BY")
private BigDecimal deletedBy;
#Column(name = "DOC_BLOB", nullable = false)
#JsonIgnore
private byte[] docBlob;
#Column(name = "DOC_NAME", nullable = false, length = 100)
private String docName;
#Id
private BigDecimal id;
#Column(name = "ORDER_BY")
private BigDecimal orderBy;
#Column(name = "UPDATE_DATE")
private Timestamp updateDate;
#Column(name = "UPDATED_BY")
private BigDecimal updatedBy;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name="created_by", referencedColumnName="id")
})
private User faqCreatedBy;
}
User entity:
#Entity
#Table(name = "USERS", catalog="abc")
#JsonInclude(Include.NON_NULL)
public class User extends EntityLog{
private BigDecimal id;
private BigDecimal edipi;
private String firstname;
private String lastname;
private String email;
..///
private Set<UsersRoles> userRoles;
private Set<UsersUnit> usersUnit;
#Id
#Column(name="id")
public BigDecimal getId() {
return id;
}
...///
#Column
#JsonIgnoreProperties({ "faqCreatedBy" })
#OneToMany(fetch = FetchType.EAGER,mappedBy = "user",cascade = {CascadeType.ALL})
#JsonManagedReference
public Set<UsersRoles> getUserRoles() {
return userRoles;
}
...///
#Column
#JsonIgnoreProperties({ "faqCreatedBy" })
#OneToMany(fetch = FetchType.EAGER,mappedBy = "user",cascade = {CascadeType.ALL})
#JsonManagedReference
public Set<UsersUnit> getUsersUnit() {
return usersUnit;
}
////...
}
With this change I am expecting the faq to load with User entity but I am not execting UsersRoles and UsersUnit to load.
But that is not what i see. When faq loads it loads User and UsersRoles and UsersUnit. I am using Spring JPA fyi. Any leads what is wrong ? Appreciate any inputs.

JPQL returns all associated Entities

I am trying to get Order[] Array which includes all Orders where the associated document isn't received.
I tried this query and it returns the right number of rows.
#Query("Select o FROM Order o INNER JOIN o.properties p INNER JOIN p.documents d WHERE d.received = false")
Order[] findUnreceivedOrders();
The problem is, the order objects in my array includes ALL documents not only the unreceived, but I want that the object only includes the unreceived document objects.
Does anyone know how to solve this?
Thanks for help!
Order.java
#Entity
#Table(name = "orders")
#JsonIgnoreProperties(ignoreUnknown = true,
value = {"progress"})
public class Order {
#Id
#Column(name = "id", unique = true)
private String orderid;
#Column(name = "user_id")
private String userid;
#Column(name = "entrydate")
private java.sql.Date entrydate;
#Column(name = "info")
private String info;
#Column
private boolean complete;
#Column(name= "cached")
private boolean cached;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "order")
private List<Property> properties = new ArrayList<>();
#OneToOne(mappedBy = "order", cascade = CascadeType.ALL)
private BillingAdress billingAdress;
// Getter & Setter
Property.java
#Entity
#Table(name = "properties")
#JsonIgnoreProperties(ignoreUnknown = true,
value = {"progress"})
public class Property
{
#Id
#Column(name = "propertyid", unique = true )
private String id;
#Column(name = "name")
private String name;
#Column(name = "street")
private String street;
#Column(name = "zip")
private String zip;
#Column(name = "town")
private String town;
#Column
private String house_number;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "property")
private List<Landregisterfolio> landregisterfolios = new ArrayList<>();
#Column(name = "userid" )
private String userid;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "property")
private List<Document> documents = new ArrayList<>();
#ManyToOne
#JoinColumn(name = "order_id")
#JsonIgnore
private Order order;
#Column(name = "order_id", insertable = false, updatable = false)
private String orderid;
//Getter & Setter
}
Document.java
#Entity
#Table(name = "documents")
public class Document {
#Id
#Column(name="id")
private String docid;
#Column(name="name")
private String docname;
#Column(name = "received")
private Boolean received;
#Column(name = "requested")
private Boolean requested;
#Column(name ="last_contact")
private Date lastContact;
#Column(name ="intern_comment")
private String intern_comment;
#Column(name ="extern_comment")
private String extern_comment;
#Column(name="fees")
private double fees;
#ManyToOne
#JoinColumn(name = "property_propertyid")
#JsonIgnore
private Property property;
#Column(name = "property_propertyid", insertable = false, updatable = false)
private String propertyid;
//Getter & Setter
}
Probably you can map #ManyToOne Order to your Document entity and after use for Order entity
#JoinColumnOrFormula(formula = #JoinFormula("(select d.id from documents d WHERE d.order_id = id AND d.received = false"))
List<Document> unreceivedDocuments;
U have list of Property in Order and list of Document in Property. So if u have one Document with status not received in your list u will have this Order.
Thanks to #pdem !
Used "join fetch", changed my lists to sets and it works fine.

Hibernate One to many mapping override

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

Referential integrity constraint violation error in JPA

I am trying to parse a web request and save to database. I have 3 models and first node is virtualDocument. This is the uniq table (according to request url). VirtualRequest table has all erquest bodies and HttpHeaderList table has all thhp headers according to their virtualRequest bean id.
when I tried to save the first log I got and error like this;
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FK1TW2G47F7A47580KQVMDJWGBQ: PUBLIC.T_VIRTUAL_REQUEST FOREIGN KEY(REQUEST_ID) REFERENCES PUBLIC.T_VIRTUAL_DOCUMENT(DOCUMENT_ID) (65)"; SQL statement:
insert into t_virtual_request (request_id, media_type, method_type, request_url) values (null, ?, ?, ?) [23506-192]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.192.jar:1.4.192]
here is VirtualDocument bean
#Entity
#Table(name = "t_virtual_document")
public class VirtualDocument {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "document_id")
private long documentId;
#Column(name = "real_url", unique = true)
private String realURL; //uniq
#Column(name = "virtual_url", unique = true)
private String virtualURL; //uniq
#Column(name = "simulation_mode", columnDefinition = "varchar(10) default 'STOP'")
private String simulationMode;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "request_id")
private List<VirtualRequest> requestList;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "response_id")
private List<VirtualResponse> responseList;
//getter setter without any annotation
}
here is VirtualRequest bean;
#Entity
#Table(name = "t_virtual_request")
public class VirtualRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "request_id")
private long requestId;
#Column(name = "request_url")
private String requestURL;
#Column(name = "method_type")
private String methodType;
#Column(name = "media_type")
private String mediaType;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "header_id")
private List<HttpHeaderList> requestHeaders;
//getter setter without any annotation
}
here is HeaderList bean;
#Entity
#Table(name = "t_http_headers")
public class HttpHeaderList {
#Id
#Column(name = "header_id")
private long headerId;
#Column(name = "header_key")
private String headerKey;
#Column(name = "header_value")
private String headerValue;
}
I think this is what you want instead:
#Entity
#Table(name = "t_virtual_document")
public class VirtualDocument {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "document_id")
private long documentId;
#Column(name = "real_url", unique = true)
private String realURL; //uniq
#Column(name = "virtual_url", unique = true)
private String virtualURL; //uniq
#Column(name = "simulation_mode", columnDefinition = "varchar(10) default 'STOP'")
private String simulationMode;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualDocument")
private List<VirtualRequest> requestList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualDocument")
// Note the mappedBy parameter. This points to the property in the entity that owns the relationship (in this case the VirtualResponse).
private List<VirtualResponse> responseList;
//getter setter without any annotation
}
#Entity
#Table(name = "t_virtual_request")
public class VirtualRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "request_id")
private long requestId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "document_id")
private VirtualDocument virtualDocument;
#Column(name = "request_url")
private String requestURL;
#Column(name = "method_type")
private String methodType;
#Column(name = "media_type")
private String mediaType;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualRequest")
private List<HttpHeaderList> requestHeaders;
//getter setter without any annotation
}
#Entity
#Table(name = "t_http_headers")
public class HttpHeader { /*Note this is a more appropriate name for the entity since it holds the data of a single header.*/
#Id
#Column(name = "header_id")
private long headerId;
#Column(name = "header_key")
private String headerKey;
#Column(name = "header_value")
private String headerValue;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "request_id")
private VirtualRequest virtualRequest
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "response_id")
private VirtualResponse virtualResponse;
}
Updated the answer to add mapping the headers to the request entity.

Making one entity to have two association with other same entity

I have two entity "user" and "vehicle".
In this user can be a owner or driver of vehicle
If user is owner he will have one to many relation with vehicle that is working fine
But if user is driver he will have one to one relation with vehicle.
I am facing the problem how make two type association between two entity at the same time.
I am posting code below that may help
UserTravelDO
#Entity
#Table(name = "usertraveldo")
public class UserTravelDO implements Serializable {
#GenericGenerator(name = "gen", strategy = "increment")
#GeneratedValue(generator = "gen")
#Id
private int userid;
private String username;
private String password;
private String hint;
private String firstname;
private String middlename;
private String lastname;
private Boolean status;
#JoinColumn(name = "addressid")
#OneToOne(cascade = CascadeType.ALL)
private AddressTravelDO address;
#JoinColumn(name = "roleid")
#ManyToOne(cascade = CascadeType.ALL)
private RoleMasterDO role;
#JsonIgnore
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<VehicleTravelDO> vehicle = new ArrayList<VehicleTravelDO>();
//#JsonIgnore
#OneToOne(mappedBy="driver",fetch = FetchType.EAGER)
private VehicleTravelDO driverofvehicle;
private java.sql.Date modificationdate = new java.sql.Date(new java.util.Date().getTime());
private java.sql.Date creationdate = new java.sql.Date(new java.util.Date().getTime());
private String createdby;
private String modifiedby;
//getters and setters are below
}
VehicleTravelDO
#Entity
#Table(name = "vehicle")
public class VehicleTravelDO implements Serializable {
#GenericGenerator(name = "gen", strategy = "increment")
#GeneratedValue(generator = "gen")
#Id
private int vehicleid;
private String vehicletype;
private String vehiclenumber;
private int totalseats;
private int availableseats;
#JsonIgnore
#JoinColumn(name = "user_id")
#ManyToOne(fetch = FetchType.EAGER)
private UserTravelDO user;
//#JsonIgnore
#OneToOne(fetch = FetchType.EAGER)
private UserTravelDO driver;
//Getters and setters are below
}
After doing this foreign key are getting generated at user and vehicle table.When i insert a vehicle with a user(driver) vehicle id is not getting inserted at the user table but at vehicle table userid(driverid) is getting
inserted.

Categories

Resources