I am having a problem when I perform merge parent table, the existing child records will be insert rather than update.
For example, Member(Parent) and Address(Child) tables,
public class Member implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private int id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "member", cascade = CascadeType.ALL)
public List<Address> addressList;
}
public class Address implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int address_id;
#Column(name = "member_id")
private int mem_id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "member_id", referencedColumnName = "id", insertable = false, updatable = false)
})
public Member member;
}
While I perform changes and merge(Member), the address record is being inserted rather than update the existing record.
Does anyone know what would be the reason?
when you perform changes do you set correct address_id ? . Do some debugging and find address_id match with existing id in Address table.
in my approach class will look like below. I don't see need of member_id attribute. because it is same as id attribute of member.
public class Address implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int address_id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "member_id", nullable = false)
public Member member;
public void setMember(Member member) {
this.member = member;
}
}
I can't see any parent child relationship in your snapshot code.
Please amend the code for child class with below code to create the inheritance relationship.
public class Child extends Member implements Serializable{
Extending the Child class to the Parent(Member) will reflect the required changes related to lazy loading.
Related
How to make a column cascade enable only for insertion not update and delete.
Here are two class. There are #ManyToOne relationship between Qualification and Department. At the time of insertion I want to insert new department with qualification. But at the time of update of qualification I don't want to update department. How can I configure that??
#Table(name = "department")
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
}
#Table(name = "qualification")
public class Qualification implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
private Integer passingYear;
private String result;
#ManyToOne(optional = true, cascade = { CascadeType. ? }, fetch = FetchType.EAGER)
#JoinColumn(name = "department_id", referencedColumnName = "id")
private Department department;
}
CascadeType.PERSIST is what you are looking for. The various CascadeType enums essentially say, which persistence operation of EntityManager persist/merge/remove etc. should cascade to the objects of an association.
I have two entity classes.
Order.java
#Entity
#Table(name = "order_table")
public class Order implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false, insertable=false, updatable=false)
private Set<Item> items;
// getters & setters & toString
Item.java
#Entity
#Table(name = "item")
public class Item implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#Column(name = "order_id", nullable = false)
private Long orderId;
// getters & setters && toString
I created a test class like this:
#Test
public void createOrderWithItems() {
Item item = new Item();
item.setName("Iron Man");
Order order = new Order();
order.setName("Toy");
order.getItems().add(item);
Order created = service.createOrder(order);
Order orderById = service.getOrderById(order.getId());
System.out.println("Created Order: " + orderById);
Item itemById = service.getItemById(item.getId());
System.out.println("Created item: " + itemById);
Assert.notNull(created.getId(), "Order ID is Null");
}
Test is green but if you check output, you'll see that orderId field in the Item class is null.
Created Order: Order{id=1, name='Toy', items=[Item{id=2, name='Iron Man', orderId=null}]}
Created item: Item{id=2, name='Iron Man', orderId=null}
Does JPA not update this column in the db automatically? Is this column is redundant? If so, how can I retrieve this information from test code?
You need to set orderId explicitly.
item.setOrderId(order.getId());
order.getItems().add(item);
You can create a method addItem(Item item) in your Order class and hide this logic within it.
Cascading will create an entry in db but it won't initialize field. JPA annotations just indicate to JPA provider how to perform mapping between entity and table.
Moreover, check your annotations. #JoinColumn should be used in the entity which owns the relationship (the corresponding table has column as a foreign key). Check the top answer for this question for detailed explanations: What's the difference between #JoinColumn and mappedBy when using a JPA #OneToMany association
I'm with some problems trying to persist an object and its items, here're my classes:
#Entity(name = "Contract")
#Table(name = "contract")
public class Contract implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private Long id;
#OneToMany(mappedBy = "idContract", cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private List<ContractItem> contractItem;
//getters & setters...
}
.
#Entity(name = "ContractItem")
#Table( name = "contract_item")
public class ContractItem implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private Long id;
#Column(name = "id_contract")
private Long idContract;
//getters & setters...
}
I'm extending JpaRepository im my repositories and using .save(contract) to persist but every time my application only persists the contract not de items, I've already tried CascadeType.ALL, MERGE and PERSIST in which either the result is the same, or I get an exception that my idContract must not be null.
Need some help here guys, thanks in advance !
Suppose we have entity A that contains a list of entities with type B (with lazy initialization).
Entity B has one BLOB field and some other, that doesn't contain much data.
How can I, using hibernate criteria query, get entity A with it's fields and each A-entity with list of Bs, but every B-entity without the BLOB field ?
Also, I do not want to extract As and iterate them to get Bs. (I now, how to use 'Projections' to extract just Bs with required fields).
Here is some code sample:
A-entity:
#Entity
#Table(name = "A")
public class A implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
#Cascade(CascadeType.ALL)
private List<B> list = new LinkedList<>();
}
B-entity:
#Entity
#Table(name = "B")
public class B implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name = "data", nullable = false)
#Lob
private byte[] data;
#ManyToOne(targetEntity = A.class, fetch = FetchType.EAGER)
#JoinColumn(name = "A_id", nullable = false)
private A a;
}
I have two entities. One is the parent (for which I have a projection) and the other entity has FK relation with the parent. My parent entity does "not" have bidirectional relationship (mappedBy).
How do I expose/get the child entity in the projection I have for the parent.
Here is how I want.
Parent:
public class EntityA implements java.io.Serializable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ENTITYAID", unique = true, nullable = false)
private Integer entityAID;
......
}
Child:
public class EntityB {
#EmbeddedId
private EntityBPk entityBPk;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ENTITYAID", referencedColumnName = "ENTITYAID",insertable=false,updatable=false)
private EntityA entityA;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ENTITYCID", referencedColumnName = "ENTITYCID",insertable=false,updatable=false)
private EntityC entityC;
#Column(name = "DUMMY")
private String dummy;
}
I want to access EntityB from EntityA's projection. Something like below.
Projection for EntityA:
#Projection(name = "projEntityA", types = { EntityA.class })
public interface EntityAProjection {
.....
Set<EntityB> getEntityBs();
}
Note:
But I don't have any reference of EntityB inside EntityA (since I don't want bidirectional relationship)
This may not be needed. But just FYI.
public class EntityBPk implements Serializable {
#Column(name = "ENTITYAID", nullable = false)
private Integer entityAID;
#Column(name = "ENTITYCID", nullable = false)
private Integer entityCId;
}
Thanks
Bharath