JPA : Delete object from unidirectional many-to-many relationship - java

I have a unidirectional relation between two entities and I want to remove property object from join table only. I tried this but it only removes the property object from template and not from database join table. How can I remove it from join table:
template.getProperties().remove(property);
Entity calss:
#Table(name = "template")
public class GridTemplate {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_grid")
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "grid_property",
joinColumns =
#JoinColumn(name = "id_grid", referencedColumnName = "id"),
inverseJoinColumns =
#JoinColumn(name = "id_property", referencedColumnName = "id"))
private List<Property> properties;
}
join table:
CREATE TABLE [dbo].[grid_property](
[id_grid] [int] NOT NULL,
[id_property] [int] NOT NULL,
CONSTRAINT [PK_grid_property] PRIMARY KEY CLUSTERED
(
[id_grid] ASC,
[id_property] ASC)

Related

correct way to create relationship in hibernate

i am having a mysql table relation with following criteria.
id - auto_increment, primary
a_id - FK to test_table primary key, index present
a_parent_id - FK to test_table primary key, index present
(a_id + a_parent_id) has unique constrain
table entries example
a_id a_parent_id
1 null
2 null
3 1
4 1
5 2
6 5
6 4
currently, i have mapped test_table in hibernate
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false)
private Long id;
#Column
private String comment;
what is the correct way to map relation table in hibernate?
As you specify that you can have multiple children/parents and from the looks of the example data, I chose to go with Lists of parents/children instead of just chaining the relationship.
#Entity
#Table(name = "test_table")
public class Test {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false)
private Long id;
#Column
private String comment;
#ManyToMany(targetEntity = Test.class)
#JoinTable(name = "relation", joinColumns = {
#JoinColumn(referencedColumnName = "a_id") }, inverseJoinColumns = {
#JoinColumn(referencedColumnName = "a_parent_id") })
private List<Test> parents;
#ManyToMany(targetEntity = Test.class)
#JoinTable(name = "relation", joinColumns = {
#JoinColumn(referencedColumnName = "a_parent_id") }, inverseJoinColumns = {
#JoinColumn(referencedColumnName = "a_id") })
private List<Test> children;
}
To find the parents, you look at the relation table with an SQL like
SELECT a_parent_id FROM relation WHERE a_id = ?
For the children you switch the columns like this:
SELECT a_id FROM relation WHERE a_parent_id = ?
This behavior should be represented by the #JoinTable annotations.

Java: Repeated column in mapping for collection

I am trying to create a OneToMany mapping with a LinkedHashMap for my main entity B, that contains the entities VC and P, but I am getting the following error:
Repeated column in mapping for collection:
com.test.model.B.pricing column: b_name
I could be wrong, but I believe that it has something to do with the #JoinColumns or #MapKeyJoinColumn annotation, as I have not done anything like this before, so I am quite sure that I am doing this part incorrectly.
My goal is that I should be able to provide the three fields:
b_name pc and c_id e.g. the VC/VCId
in order to get the a and d_a e.g. P.
Also, if there is a better way to structure things, then I am all ears, as I personally do not really like how I have set up my tables tbh (would be nice if I could just have the b and b_p tables, where the b_p could just have all five fields (key and value) from the p map).
Here is my main entity
#Setter
#Getter
#Entity
#Table(name = "b")
public class B implements Serializable {
#Id
#Column(nullable = false)
private String name;
#OneToMany(cascade = CascadeType.PERSIST)
#JoinTable(
name = "b_p",
joinColumns = #JoinColumn(name = "b_name", referencedColumnName = "name"))
#MapKeyJoinColumns({
#MapKeyJoinColumn(name = "b_name"),
#MapKeyJoinColumn(name = "p_c"),
#MapKeyJoinColumn(name = "c_id")
})
private Map<VC, Price> pricing = new LinkedHashMap<>();
...
}
The Key to the map
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "v_c")
public class VC implements Serializable {
#EmbeddedId private VCId vcId;
}
The key's PK/Composite Key
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#Embeddable
public class VCId implements Serializable {
#Column(name = "b_name")
private String bName;
#Column(name = "p_c")
private SomeEnum pc;
#Column(name = "c_id")
private String cId;
}
The value for the map
#Setter
#Getter
#NoArgsConstructor
#Embeddable
#Entity
#Table(name = "price")
public class Price implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#Column(name = "amount")
private BigDecimal amount;
#Column(name = "discount_amount")
private BigDecimal discountAmount;
}
DB tables
CREATE TABLE b
(
name VARCHAR(100) NOT NULL PRIMARY KEY
...
);
CREATE TABLE v_c
(
bundle_name VARCHAR(100) NOT NULL,
physical_currency TEXT NOT NULL,
coin_id VARCHAR(50) NOT NULL,
FOREIGN KEY (b_name) REFERENCES b (name) ON DELETE CASCADE,
PRIMARY KEY (b_name, p_c, c_id)
);
CREATE TABLE p
(
id BIGSERIAL NOT NULL PRIMARY KEY,
amount NUMERIC,
discount_amount NUMERIC DEFAULT 0.00
);
CREATE TABLE b_p
(
bname VARCHAR(100) NOT NULL,
p_c TEXT NOT NULL,
c_id VARCHAR(50) NOT NULL,
price_id BIGSERIAL NOT NULL,
FOREIGN KEY (b_name, p_c, c_id) REFERENCES v_c (b_name, p_c, c_id) ON DELETE CASCADE,
FOREIGN KEY (price_id) REFERENCES price (id) ON DELETE CASCADE,
PRIMARY KEY (b_name, p_c, c_id)
);
To prevent repeated mapping error, you just have to specify which join should update the column like such:
#OneToMany(cascade = CascadeType.PERSIST)
#JoinTable(name = "bundle_pricing",
joinColumns = #JoinColumn(name = "bundle_name",
referencedColumnName = "name"))
#MapKeyJoinColumns({
#MapKeyJoinColumn(name = "bundle_name", insertable = false, updatable = false),
#MapKeyJoinColumn(name = "physical_currency"), #MapKeyJoinColumn(name = "coin_id")})
private Map<VirtualCurrency, Price> pricing = new LinkedHashMap<>();
NOTE the insertable = false, updatable = false for bundle_name in the MapKeyJoinColumn
remove the #MapKeyJoinColumn(name = "bundle_name") from MapKeyJoinColumns, because when we are creating the JoinColumn in JoinTable it will create the column we don't need to mention it again.
#JoinTable(
name = "bundle_pricing",
joinColumns = #JoinColumn(name = "bundle_name", referencedColumnName = "name"))
#MapKeyJoinColumns({
#MapKeyJoinColumn(name = "physical_currency"),
#MapKeyJoinColumn(name = "coin_id")
})

Hibernate mapping entity with a Set of itself

I have this class in my code
#Entity(name = "Point")
#Table(name = "Point")
public class Point extends com.lsikh.unlmaps.base.Entity<Integer>{
private Integer id;
...
...
private Set<Point> connections = new HashSet<Point >();
I need to relate a Point entity with many other Point's object in that Set and retrieve.
This are my tables in the database
CREATE
TABLE Point(
id INTEGER UNIQUE AUTO_INCREMENT NOT NULL,
...
...
PRIMARY KEY (id )
);
CREATE
TABLE Connections(
idA INTEGER NOT NULL,
idB INTEGER NOT NULL,
FOREIGN KEY (idA ) REFERENCES Point (id),
FOREIGN KEY (idB ) REFERENCES Point(id)
);
Which is the correct set of hibernate notations to do this.
I think could be
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "Connections", joinColumns = {
#JoinColumn(name = "id") }, inverseJoinColumns = {
#JoinColumn(name = "idA") })
public Set<Point> getConnections() {
return connections;
}
But I'm having problems to do the map and I'm not sure.
According to the javadoc the joinColumns:
The foreign key columns of the join table which reference the primary
table of the entity owning the association
So assuming that idA is the id of the owning entity in the join table the mapping should be:
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "Connections", joinColumns = {
#JoinColumn(name = "idA") }, inverseJoinColumns = {
#JoinColumn(name = "idB") })
public Set<Point> getConnections() {
return connections;
}

How to do One to One association in hibernate with foreign key and join table and unidirectional

I wish to have a one to one association with a join table in unidirectional way. -
Tables :
A (A_id, D_id, A_Data)
B (A_id, C_id) // Join table just contain relation between A and C
C (C_id, C_Data)
Class A {
.
.
#OneToOne(cascade = CascadeType.ALL)
#JoinTable(name = "B",
joinColumns = #JoinColumn(name = "A_id", referencedColumnName = "A_id"),
inverseJoinColumns = #JoinColumn(name = "C_id", referencedColumnName = "C_id"))
private C c;
}
I am using hibernate with jpa 2.0.
Entity D is not important in the model hence ignored.
I only wish to read data ,hence insert/update/delete use cases should not be concern, but one can suggest best practice in that case also.
This setup does not work. Can some one suggest how to do it in correct way?
It gives following exception
org.hibernate.MappingException: Unable to find column with logical name: A_id in org.hibernate.mapping.Table(A) and its related supertables and secondary tables
In order to get your desired schema:
// Given the following C entity
#Entity
public class C {
#Id
#Column(name = "C_ID")
private long id;
private String C_Data;
//...
}
// A Entity should be
#Entity
public class A {
#Id
#Column(name = "A_ID")
private long id;
private String A_Data;
#OneToOne(cascade = CascadeType.ALL )
#JoinTable(name = "B", joinColumns = #JoinColumn(name = "A_id"), inverseJoinColumns = #JoinColumn(name = "C_id", unique = true))
private C c;
//...
}
I've omitted referencedColumnName, so hibernate will map it to the entity primary key.
Note also that A_id column of B table will be the primary key.

JPA many to one/one to many query

I would like to create JPA query based on this tables
**category**
(pk)CategoryID int (10)
category VARCHAR (45)
**templatecat**
(pk/fk)templateId int(10)
(pk/fk)categoryId int (10)
**template**
(pk)templateId int (10)
template madiumtext
I also have a "tempaltecat" table that holds foreign keys for category and template table.I`d like to create query that finds all templates in template table based on category and vice versa.
Here is my table mapping
#Entity
#Table(name = "category")
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name = "templatecat", joinColumns = { #JoinColumn(name = "categoryId", unique = true) }, inverseJoinColumns = { #JoinColumn(name = "templateId") })
private Set<Template> template;
#Entity
#Table(name = "template")
#ManyToOne(optional = true)
#JoinTable(name = "templatecat", joinColumns = { #JoinColumn(name = "templateId") }, inverseJoinColumns = { #JoinColumn(name = "categoryId") })
private Category category;
Thanks in advance
It looks like a #ManyToMany relationship,
Instead of using #OneToMany and #ManyToMany, you can use the following configuration:
In Category class:
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "templatecat", joinColumns = { #JoinColumn(name = "categoryId", unique = true) }, inverseJoinColumns = { #JoinColumn(name = "templateId") })
private Set<Template> templates;
In Template class:
#Entity
#Table(name = "template")
#ManyMany(optional = true, mappedBy="templates");
private Set<Category> categories;
If you want to see all Templates of a given Category, the query would be:
select o.templates from Category o where o.id = ?
The reverse works as well (all Categories from a Template)
select o.categories from Template o where o.id = ?
Hope it has helped you.

Categories

Resources