Not able to delete in #OneToMany relationship spring data jpa - java

In my spring boot project, I have one LineItem entity below is the code
#Entity
#Table(name = "scenario_lineitem")
#Data
#NoArgsConstructor
public class LineItem implements Cloneable {
private static Logger logger = LoggerFactory.getLogger(GoogleConfigConstant.class);
#Id
#GeneratedValue(strategy = IDENTITY)
private BigInteger lineItemId;
#Column
private String name;
#OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL, CascadeType.PERSIST, CascadeType.MERGE })
#JoinColumn(name = "line_item_meta_id")
private List<QuickPopValue> quickPopValues;
}
Another entity is
#Entity
#Table(name = "quick_pop_value")
#Data
#NoArgsConstructor
public class QuickPopValue implements Cloneable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "quick_pop_value_id", columnDefinition = "bigint(20)", unique = true, nullable = false)
private BigInteger quickPopValueId;
#Column(name = "column_name")
private String columnName;
#Column(name = "value")
private String value;
#Column(name = "formula", columnDefinition = "longtext")
private String formula;
}
Now I am trying to delete QuickPopValue one by one but it's not getting deleted and not getting any exception as well.
Below is the delete code :
List<QuickPopValue> quickPopValues = sheetRepository.findByColumnName(columnName);
for (QuickPopValue qpValue : quickPopValues) {
quickPopValueRepository.delete(qpValue);
}

Such behavior occurs when deleted object persisted in the current session.
for (QuickPopValue qpValue : quickPopValues) {
// Here you delete qpValue but this object persisted in `quickPopValues` array which is
quickPopValueRepository.delete(qpValue);
}
To solve this you can try delete by id
#Modifying
#Query("delete from QuickPopValue t where t.quickPopValueId = ?1")
void deleteQuickPopValue(Long entityId);
for (QuickPopValue qpValue : quickPopValues) {
quickPopValueRepository.deleteQuickPopValue(qpValue.getQuickPopValueId());
}

Related

Hibernate JoinFormula partial PK EmbeddedId

I have a table that holds events where the data is stored as a JSON object.
What i'am trying to do is have different entities mapped to the same table, because some of these events need to join with other tables to be useful.
What i tried doing:
EntityA is the "default" entity for the table, all events are received in this entity an them stored.
#Entity(name = "entity_a")
#Table(name = "table_a")
public class EntityA {
#Id
private UUID id;
#Column(name = "fielda")
private String fieldA;
#Column(name = "fieldb")
private Integer fieldB;
#Column(name = "json_field")
private Object jsonField;
}
EntityAB is a map of the same table with a new field that is a join with another table.
#Entity(name = "entity_ab")
#Table(name = "table_a")
public class EntityAB {
#Id
private UUID id;
#Column(name = "fielda")
private String fieldA;
#Column(name = "fieldb")
private Integer fieldB;
#Column(name = "json_field")
private Object jsonField;
#ManyToOne
#ManyToOne
#JoinColumnsOrFormulas(value = {
#JoinColumnOrFormula(formula = #JoinFormula(value = "JSON_VALUE(jsonField, '$.field_id_a')", referencedColumnName = "field_id_a")),
#JoinColumnOrFormula(formula = #JoinFormula(value = "JSON_VALUE(jsonField, '$.field_id_b')", referencedColumnName = "field_id_b")),
#JoinColumnOrFormula(formula = #JoinFormula(value = "JSON_VALUE(jsonField, '$.fieldc')", referencedColumnName = "fieldc")),
})
private EntityB entityB;
}
EntityB is used in the EntityAB.
public class EntityB implements Serializable {
#EmbeddedId
private EntityBId id;
#Column(name = "fieldc")
private String fieldC;
}
#Embeddable
public class EntityBId implements Serializable {
#Column(name = "field_id_a")
private String fieldIdA;
#Column(name = "field_id_b")
private Integer fieldIdB;
#Column(name = "field_id_c")
private Integer fieldIdC;
}
When starting the application, it gives me this error:
referencedColumnNames(field_id_a, field_id_b, fieldc) of EntityAB.entityB referencing EntityB not mapped to a single property
If i dont use the fields "field_id_a" and "field_id_b" (EmbeddedId) in the join, it works, but it's not the right join. From what i have searched it looks like i can't have a parcial PK join when using "EmbeddedId", is that correct?

How to get parent entity with all child entities and child entities of children in Spring/JPA/Hibernate with Lombok

I have these entities where Shop entity is parent:
#Data
#NoArgsConstructor
#Entity
#DynamicUpdate
#Table(name = "Shop", schema = "public")
public class ShopDao {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
private String name;
private String processedStatus;
#OneToMany(mappedBy = "shopDao", cascade = CascadeType.ALL, orphanRemoval = true)
private List<BookDao> bookDaoList;
}
#Data
#NoArgsConstructor
#Entity
#ToString(exclude = {"shopDao"})
#Table(name = "Book", schema = "public")
public class BookDao {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
private String name;
private String author;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "other_id", referencedColumnName = "id")
private OtherDao otherDao;
#ManyToOne
#JoinColumn(name = "shop_id", nullable = false)
private ShopDao shopDao;
}
#Data
#NoArgsConstructor
#Entity
#ToString(exclude = {"bookDao"})
#Table(name = "Other", schema = "public")
public class OtherDao {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
private String metadata;
#OneToOne(mappedBy = "otherDao", fetch = FetchType.EAGER)
private BookDao bookDao;
}
And these are repos:
#Repository
public interface ShopRepo extends JpaRepository<ShopDao, Long> {
#EntityGraph(attributePaths = {"bookDaoList"})
List<ShopDao> findAllByProcessedStatus(String processedStatus);
}
#Repository
public interface BookRepo extends JpaRepository<BookDao, Long> {
}
#Repository
public interface OtherRepo extends JpaRepository<OtherDao, Long> {
}
When i'm using findAllByProcessedStatus() function, i get BookList inside Shop object correctly, but each Book can't reach their Other objects and i get LazyInitializationException:
screenshot
How do i fix that problem?
Actually, with spring data's #EntityGraph all you need is :
#Repository
public interface ShopRepo extends JpaRepository<ShopDao, Long> {
#EntityGraph(attributePaths = {"bookDaoList.otherDao"})
List<ShopDao> findAllByProcessedStatus(String processedStatus);
}
This is the most convenient way.
For more complex relations, you could define a #NamedEntityGraph, and provide subgraphs, like so.
What I find intriguing, is that the BookDao is the owner of this relation, so I would expect it to be eagerly loaded, since you haven't specified a the Lazy fetch mode explicitly ...

Java Spring Data App doesn't save sub-objects

I'm trying to build build service, which saves object with sub-objects, but getting error. In result object data fields saved, but sub-object not.
I have the next object. The main is Order and sub-object is Partner:
#Getter
#Setter
#Entity
#Table(name = "orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "order_id")
private int orderId;
#OneToMany(mappedBy = "order", fetch = FetchType.EAGER,
cascade = CascadeType.ALL)
private Set<Partner> partners;
}
#Getter
#Setter
#Entity
#Table(name = "partners")
public class Partner implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "partner_id")
private int id;
#ManyToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "order_id", nullable = false)
private Order order;
}
I use standard embedded method "save" from Spring Jpa Repository:
#Repository
public interface OrdersRepository extends JpaRepository<Order, Integer> {
}
and service, which call this Repository:
#Service
public class OrdersServiceImpl implements OrdersService {
#Autowired
private OrdersRepository repository;
#Override
public Order save(Order order) {
return repository.save(order);
}
}
Does someone have an idea why Partners are not saved?
Thanks a lot!
Because the relationship owner is Partner, so that you need to save the Order first. Or you can put cascade = CascadeType.PERSIST on private Order order;

How to save data-from-parent-to-child-tables-based-on-entities-in-spring-jpa

I have a table master table user ,topics table and comments table
where in for a single topic there can be multiple comments
user table will be already populated.
I will get a post request to save the topic with structure like below
{
"topicId":"T001",
"title":"stackoverflow",
"commentBeans":[
{
"comment":"developer platform"
},
{
"comment":"developer communtiy"
}
]
}
Frameworks used:
spring boot
JPA
DB : postgressql
I am able to save the data the traditional way (i.e get the request and save topic bean first. get the primarykey from saved entity and loop the list of commentbean where user num will be set dynamically by another get service and save them)
I wanted to know if there is anyway to save the data with single save query.
#Entity
#Table(name ="user")
public class User implements Serializable {
#Id
#Column(name = "user_num")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userNum;
#Column(name = "user_id")
private String userId;
#Column(name = "username")
private String userName;
}
#Entity
#Table(name = "topics")
public class TopicBean implements Serializable {
#Id
#Column(name = "topic_num")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long topicNum;
#Column(name = "topicId")
private String topicId;
#Column(name = "title")
private String title;
#OneToMany(mappedBy="topicBean")
private List<CommentBean> commentBeans;
}
#Entity
#Table(name = "comments")
public class CommentBean implements Serializable {
#EmbeddedId
private CommentBeanKey key;
#Column(name = "comment")
private string comment;
#ManyToOne
#JoinColumn(name="topic_num")
private TopicBean topicBean;
#ManyToOne
#JoinColumn(name="user_num")
private TopicBean topicBean;
}
#Embeddable
public class CommentBeanKey implements Serializable{
private static final long serialVersionUID = 5889249943605061539L;
#Column(name ="topic_num")
private Long topicNum;
#Column(name ="user_num")
private Long userNum;
}
I saw the below link and am little worried if am doing the wrong way. any help is appreciated.
https://thoughts-on-java.org/hibernate-tips-how-to-map-an-entity-to-multiple-tables/
Parent.java
#Entity
#Table(name = "parent")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int parentId;
private String name;
#OneToMany(mappedBy="parent",fetch=FetchType.LAZY,cascade = CascadeType.PERSIST)
private List<Child> child = new ArrayList<Child>();
}
Child.java
#Entity
#Table(name = "child")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class Child {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int childId;
private String account;
#ManyToOne(fetch = FetchType.LAZY, targetEntity = Parent.class)
#JoinColumn(name="parentId", referencedColumnName = "parentId", nullable = false)
private Parent parent;
}
Controller.java
//save Child with Parent at same
#PostMapping(value = "/onetomany")
public String OneToMany(#RequestBody Parent parent)
{
System.out.println("Parent: "+parent.toString());
for (Child child : parent.getChild()) {
child.setParent(parent);
}
parent.setChild(parent.getChild());
parentRepository.save(parent);
return "saved";
/*{
"name":"Romil",
"child":[
{"account":"1"},
{"account":"2"}
]
}*/
}
//save Child with Parent's ID
#PostMapping(value = "/onetomanyPID")
public String OneToMany(#RequestBody Child child)
{
child.setParent(child.getParent());
childRepository.save(child);
return "saved";
/*{
"account":"3",
"parent":{
"parentId":"1",
"name":"Romil"
}
}*/
}

Spring CrudRepository - 'not equals' condition for child table(which is as List)

I've two entity with #OneToMany relationship
First Entity
#Entity
#Table(name = SchemaConstant.RESCHEDULE_TABLE_NAME)
public class RescheduleRequestEntity extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "RESCHEDULE_ID_GEN")
#SequenceGenerator(
name = "RESCHEDULE_ID_GEN",
allocationSize = 1,
sequenceName = SchemaConstant.RESCHEDULE_SEQUENCE_NAME)
private Long id;
private String adviseNo;
private LocalDate adviseDate;
private Long customerId;
#Enumerated(value = EnumType.STRING)
private AdviceStatus status;
#OneToMany(mappedBy = "reschedule", fetch = FetchType.LAZY)
private List<RescheduleDetailEntity> accountDetails;
}
Second Entity
#Entity
#Table(name = "RESCHEDULE_DETAILS")
public class RescheduleDetailEntity extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "RESCHEDULE_DETAILS_ID_GEN")
#SequenceGenerator(
name = "RESCHEDULE_DETAILS_ID_GEN",
allocationSize = 1,
sequenceName = "S_RESCHEDULE_DETAILS")
private Long id;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ACCOUNT_ID", nullable = false)
private AccountEntity account;
#Enumerated(value = EnumType.STRING)
private AdviceStatus status;
#Enumerated(value = EnumType.STRING)
private TenureType tenureType;
private Integer tenure;
#ManyToOne
#JoinColumn(name = "ADVISE_ID")
private RescheduleDetailEntity reschedule;
}
AND Enum
public enum AdviceStatus {
OPEN,
ACTIVE,
CLOSE
}
I want to fetch data with condition Like
SELECT *
FROM RESCHEDULEREQUESTENTITY R, RESCHEDULEDETAILENTITY D
WHERE R.ID = :PID
AND D.ADVISEID = R.ID
AND D.STATUS <> "CLOSE"
"Data fetch from RescheduleRequestEntity with data from RescheduleDetailEntity where RescheduleDetailEntity.status is not equal "CLOSE" where "Status" is Enum type".
I create a JPA Repository class like following for fetch data
#Repository
public interface RescheduleRequestRepository
extends JpaRepository<RescheduleRequestEntity, Long>, JpaSpecificationExecutor {
Optional<RescheduleRequestEntity> findByAdviseNo(String adviceNo);
Optional<RescheduleDetailEntity> findByIdAndAccountDetails_StatusNot(
Long adviceId, AdviceStatus status);
}
but it's not fetch data with my desired condition,it's not ignore data which have Status "CLOSE"
You can make it a custom query using #Query annotation.

Categories