Embeddable is creating 2 tables jpa springs - spring

I have below entites
AbstractOrderEntry :
#Getter #Setter
public class AbstractOrderEntry implements Serializable
{
#ElementCollection
private List<DiscountValue> discountValues = new ArrayList<>();}
}
CartEntry extending AbstractOrderEntry
#Entity
#EntityListeners(value = AuditListener.class)
#Table(name = "cartentry")
#Getter #Setter
public class CartEntry extends AbstractOrderEntry implements Serializable,Cloneable,Auditable
{
#Id
#Column(name="CartEntryID",nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
}
DiscountValueEntity:
#Embeddable
#Getter #Setter
public class DiscountValue {
private String code;
private BigDecimal value;
private BigDecimal appliedValue;
}
When I start the server it is generating to tables like
cart_discountValue
cart_discountvalue
one with camelcase and other is with lowercase.
We are also extending AbstractOrderEntry for order entity as well hence for order also 2 tables are getting created.
How can overcome this issue.Because of this issue table data is not properly persisting.
Thanks , Inadvance.
Sree

Related

Spring data JPA: embedded ID error when saving the entity

I have the following entity classes:
#Embeddable
#Getter
#Setter
public class OrganizationCyclePlageKey implements Serializable {
#Column(name = "organization_id")
Long organizationId;
#Column(name = "cycle_plages_id")
Long cyclePlagesId;
...
equals() and hashCode() methods come here
#Entity
#Table(name = "organization_cycle_plages")
#Getter
#Setter
public class OrganizationCyclePlage {
#EmbeddedId
private OrganizationCyclePlageKey id;
#ManyToOne
#MapsId("organizationId")
#JoinColumn(name = "organization_id")
Organization organization;
#ManyToOne
#MapsId("cyclePlagesId")
#JoinColumn(name = "cycle_plages_id")
CyclePlage cyclePlage;
...
other attributes
}
#Entity
#Getter
#Setter
public class CyclePlage extends AbstractEntity {
#OneToMany(mappedBy = "cyclePlage")
private Set<OrganizationCyclePlage> organizationCyclePlages;
...
}
#Entity
#DynamicUpdate
#Getter
#Setter
public class Organization extends AbstractEntity {
#OneToMany(mappedBy = "organization")
private Set<OrganizationCyclePlage> organizationCyclePlages = new HashSet<>();
...
}
SpringBoot app starts up normally without errors.
But when I try to save an instance of OrganizationCyclePlage:
OrganizationCyclePlage ocp = new OrganizationCyclePlage();
ocp.setOrganization(organization);
ocp.setCyclePlage(cyclePlage);
organizationCyclePlageRepository.save(ocp);
it raises the error when calling organizationCyclePlageRepository.save(ocp):
org.hibernate.PropertyAccessException: Could not set field value [361] value by reflection : [class com.XXXX.OrganizationCyclePlageKey.cyclePlagesId] setter of com.XXXX.OrganizationCyclePlageKey.cyclePlagesId
What's wrong with these relations?
I had to add the constructor into the OrganizationCyclePlageKey class to init the foreign keys values as well a default constructor via #NoArgsConstructor annotation:
public OrganizationCyclePlageKey(Long organizationId, Long cyclePlagesId) {
this.organizationId = organizationId;
this.cyclePlagesId = cyclePlagesId;
}
and init the OrganizationCyclePlageKey instance in the OrganizationCyclePlage class:
public class OrganizationCyclePlage {
private OrganizationCyclePlageKey id = new OrganizationCyclePlageKey();
...
}

Spring - JPA join abstract class in abstract class

I have a problem with JPA inheritance. The database model is also specially built. It contains several tables with the same attributes (the tables were intentionally cut by country) and all these tables connect to another table (OneToOne).
Here is an example of the data model:
usa_user, germany_user, austria_user. All these tables have the same attributes (id, name, address). Now the address was also built up according to the countries e.g. usa_address, germany_address, austria_address.
Now I don't know or have the problem that I have been mapping them correctly for a long time. I have the following:
// All Lombok Getter, Setter Args,...
#MappedSuperclass
public abstract Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonIgnore
private Long id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id", referencedColumnName = "id")
#JsonIgnore
private User user;
private String name;
private String addr_num;
...
}
// All Lombok Getter, Setter Args,...
#MappedSuperclass
public abstract User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonIgnore
private Long id;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
#JsonIgnore
private Address address;
private String name;
}
#Entity
#Table(name = "usa_user")
public class UsaUser extends User {}
#Entity
#Table(name = "austria_user")
public class AustriaUser extends User {}
#Entity
#Table(name = "germany_user")
public class GermanyUser extends User {}
#Entity
#Table(name = "usa_address")
public class UsaAddress extends Address {}
#Entity
#Table(name = "austria_address")
public class AustriaAddress extends Address {}
#Entity
#Table(name = "germany_address")
public class GermanyAddress extends Address {}
But unfortunately this does not work. Every time I start it JPA notices that it can't map the Entities Address - User (which is understandable because they are not entities but abstract classes). What would be the best way to solve this? I want to avoid that I have to list the attributes in all these entities because it would be redundant.
The goal is to find out how I can use a #MappedSuperclass in a #MappedSuperclass.
MappedSuperclass is not queryable and thus also not joinable. You need to map this as an abstract entity with the table per class inheritance strategy. Just switch to #Entity on the Address and User and add #Inheritance(TABLE_PER_CLASS).

Springboot add problem in oneTOMany relation

I'm writing 3 tables in the following relation:
Club class:
#Setter
#Getter
#Entity
#Table(name = "Club")
public class Club {
#Id
#GeneratedValue
private Long id;
private String name;
private String type;
private String mainPage;
private String logo;
#OneToMany(mappedBy="clubProductKey.club", cascade = CascadeType.ALL)
#JsonIgnoreProperties(value = "clubProductKey.club", allowSetters=true)
private Set<ClubProduct> clubProducts;
...
Product class:
#Setter
#Getter
#Entity
#Table(name = "Product")
public class Product {
#Id
#GeneratedValue
private Long id;
#OneToMany(mappedBy="clubProductKey.product", cascade = CascadeType.ALL)
#JsonIgnoreProperties(value = "clubProductKey.product", allowSetters=true)
private Set<ClubProduct> clubProducts;
...
ClubProduct class:
#Setter
#Getter
#Entity
#Table(name = "ClubProduct")
public class ClubProduct {
#EmbeddedId
private ClubProductKey clubProductKey;
...
ClubProductKey class:
#Setter
#Getter
#Embeddable
public class ClubProductKey implements Serializable {
#ManyToOne(cascade = {CascadeType.MERGE,CascadeType.REFRESH })
#JoinColumn(name = "club_id", referencedColumnName = "id")
#JsonIgnoreProperties(value = "clubProducts", allowSetters=true)
private Club club;
#ManyToOne(cascade = {CascadeType.MERGE,CascadeType.REFRESH })
#JoinColumn(name = "product_id", referencedColumnName = "id")
#JsonIgnoreProperties(value = "clubProducts", allowSetters=true)
private Product product;
...
ClubProductRepository class:
public interface ClubProductRepository extends JpaRepository<ClubProduct, ClubProductKey> {
public List<ClubProduct> findByClubProductKeyClub(Club club);
public List<ClubProduct> findByClubProductKeyProduct(Product product);
}
I try to save clubProduct like this:
#Service
public class ClubProductServiceImp implements ClubProductService {
#Autowired
private ClubProductRepository clubProductRepository;
...
ClubProduct savedClubProduct = clubProductRepository.save(clubProduct);
return savedClubProduct;
}
However I find that the clubProduct is not saved in the clubProducts list in the club or product entity, the list is null. Must I add lines like club.getClubProducts.add(clubProduct) or is there any other way to make it added automatically?
Thank you.
The #OnetoMany mapping in your Club class uses the attribute mappedby which means that it represents the owning side of the relation responsible for handling the mapping. However, we still need to have both sides in sync as otherwise, we break the Domain Model relationship consistency, and the entity state transitions are not guaranteed to work unless both sides are properly synchronized.
The answer is yes, you have to manage the java relations yourself so that the clubProducts gets persisted. You are using an instance of the repository class club to persist the data so , you should add a setter method like :
public void addClubProduct(ClubProduct clubProduct) {
if (clubProduct!= null) {
if (clubProduct== null) {
clubProduct= new ArrayList<ClubProduct>();
}
clubProducts.add(clubProduct);
clubProduct.setClubProduct(this);
}
}
also a method to remove it from the list and use these method in your code to set the values to the list properly before initiating save . Read related article

Why is my mapped DTO List null? What is the best way to map and persist Child Lists?

I have a simple problem - but I think "I am standing on the tube".
I have a spring boot rest api with JPA, Modelmapper, Entities and DTOs.
But the mapping doesn't work.
Entities:
#Getter
#Setter
#MappedSuperclass
public class AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
#Getter
#Setter
#Entity(name = "contacts")
public class Contact extends AbstractEntity {
#NotBlank
private String firstName;
#NotBlank
private String lastName;
#Valid
#OneToMany(mappedBy = "contact", cascade = CascadeType.ALL, orphanRemoval = true)
private List<PhoneNumber> phoneNumberList;
}
#Getter
#Setter
#Entity(name = "phone_numbers")
public class PhoneNumber extends AbstractEntity {
#NotBlank
private String label;
#NotBlank
private String number;
#ManyToOne
#JoinColumn(name = "contact_id", referencedColumnName = "id")
#Setter(value = AccessLevel.NONE)
private Contact contact;
}
The DTOs:
#Getter
#Setter
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class ContactDTO {
private Long id;
private String firstName;
private String lastName;
List<PhoneNumberDTO> phoneNumberDTOList = new ArrayList<>();
}
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class PhoneNumberDTO {
private Long id;
private String label;
private String number;
}
My ModelMapperConfig:
#Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setFieldMatchingEnabled(true)
.setFieldAccessLevel(AccessLevel.PRIVATE);
return modelMapper;
}
Repo:
public interface ContactRepository extends JpaRepository<Contact, Long{
}
Service (only the create method):
#Override
public ContactDTO createOne(ContactDTO contactDTO) {
Contact contact = modelMapper.map(contactDTO, Contact.class);
contactRepository.save(contact);
return contactDTO;
}
Is this the correct way to persist the Contact with its multiple phonenumbers?
And how can I create a simple mapping?
If i want to persist it, there comes an error:
Column 'contact_id' cannot be null

How to create sub resource with #RestRepositoryResource

We are working on a Spring Boot API.
We use #RestRepositoryResource annotation to generate endpoints.
#RepositoryRestResource(collectionResourceRel = "datarow", path = "datarow")
public interface DataRowRepository extends MongoRepository<DataRow, String>
}
In the previous example, we create a endpoint /api/datarow.
But we want to change resource path like this : /api/dataset/{id}/datarow. Is it possible with #RestRepositoryResource ?
See our model :
public class Datarow {
#Getter #Setter
private String id;
#Getter #Setter
private String datasetId;
#Getter #Setter
private Address address;
}
public class Dataset {
#Getter #Setter
private String id;
#Getter #Setter
private String name;
#Getter #Setter
private String filePath;
#Getter #Setter
private Date uploadDate;
}
See our repository :
#RepositoryRestResource(collectionResourceRel = "datarow", path = "datarow")
public interface DatarowRepository extends MongoRepository<Datarow, String> {
}
Thanks !

Resources