Spring Data Rest - Save parent entity with children - spring

I am new in Spring Data Rest. I want to save a parent entity with his children. The class are Distribution and FileIdVersion.
This is the Distribution entity.
#Entity
#DistributionValidator
public class Distribution extends AbstractAuditableJpaEntityImpl {
private static final long serialVersionUID = 1L;
#NotNull
#Length(min = 1, max = 256)
#SafeHtml
private String company;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "distribution")
#Size(max = 256)
private List<FileIdVersion> fileIdVersions = new ArrayList<>();
public Distribution() {
super();
}
public Distribution(final String company, final String name, final String topic, final ZonedDateTime uploadDate,
final ZonedDateTime setupDate, final UUID uuid, final List<FileIdVersion> fileIdVersions,
final List<Bundle> bundles, final List<String> recipientId) {
super();
this.company = company;
this.fileIdVersions = fileIdVersions;
}
}
This is the FileIdVersion entity.
#Entity(name = "bundle_file_id_version")
public class FileIdVersion extends AbstractJpaEntityImpl implements Serializable {
private static final long serialVersionUID = 1L;
#NotNull
#FileId
private String fileId;
#FileVersion
private String fileVersion;
#ManyToOne
#NotNull
#JsonIgnore
private Bundle bundle;
public FileIdVersion() {}
}
I want to save one distribution object with his fileIdVersion. I am trying something like this:
This request only persist in BBDD one record of distribution, but not persist any records in FileIdVersion entity. How I can to persist the distribution with his file id versions? Thank you in advance!!!

Related

Auto populate created_date, last_modified_date, created_by and last_modified_by in entity : Hibernate with JPA

I am new to Hibernate and JPA. I have several entities, each of which contains following four columns:
1. created_by
2. last_modified_by
3. created_date
4. last_modified_date
I would like these columns to get auto-populated while saving the associated entity.
Two sample entities are as follows:
Entity 1:
#Entity
#Table(name = "my_entity1")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity1 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
Entity 2:
#Entity
#Table(name = "my_entity2")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity2 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "description")
private String description;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
In this context, I have gone through following posts: How to autogenerate created or modified timestamp field?, How can you make a created_at column generate the creation date-time automatically like an ID automatically gets created?.
I am getting how to capture the dates fields but I cannot understand how to capture created_by and last_modified_by.
Auditing Author using AuditorAware and Spring Security...
To tell JPA about currently logged in user we will need to provide an
implementation of AuditorAware and override getCurrentAuditor()
method. And inside getCurrentAuditor() we will need to fetch currently
logged in user.
Like this:
public class AuditorAwareImpl implements AuditorAware<String> {
#Override
public String getCurrentAuditor() {
return "TestUser";
// Can use Spring Security to return currently logged in user
// return ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()
}
}
Now enable jpa auditing by using #EnableJpaAuditing
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class JpaConfig {
#Bean
public AuditorAware<String> auditorAware() {
return new AuditorAwareImpl();
}
}
Look at this to get more details....

Spring JPA Update Entity

I'm trying to update my user entity and I have an error that comes to mind:
ERROR: A NULL value violates the NOT NULL constraint of the "id" column Detail: The failed row contains (null, 1, 1)
The problem surely stems from my relationship between user and profile which is n-n
public class Utilisateur implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Integer id;
private Integer fixe;
private Boolean deleted;
private Boolean actif;
private String email;
private Integer mobile;
private String motDePasse;
private String nom;
private String prenom;
#ManyToMany
private List<Profil> profils = new ArrayList<Profil>();
public Utilisateur() {
}
}
public class Profil implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Integer id;
private String codeProfil;
private String libelleProfil;
#JsonManagedReference
#ManyToMany
private List<MenuAction> menuActions = new ArrayList<MenuAction>();
public Profil() {
}
}
How you generate value for your id?
Seems you need some way to generate value for you ID.
For example, use #GeneratedValue, like:
#GeneratedValue(strategy = IDENTITY)

Sorting with hibernate single table inheritance strategy

In my application I have three entities, BaseNotification as a parent and SmsNotification and EmailNotification as child entities which extend BaseNotification.
I am using hibernate single table inheritance strategy so all attributes fit into one table.
Lets say I have some common attributes on BaseNotification entity, and child entities have one specific attribute each (SmsNotification has mobileNumber and EmailNotification has email attribute).
public abstract class BaseNotification implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "description")
private String description;
...
}
public abstract class EmailNotification extends BaseNotification implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "email")
private String email;
...
}
public abstract class SmsNotification extends BaseNotification implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "mobileNumber")
private String mobileNumber;
...
}
Is there a way of fetching all notifications with all attributes while sorting on child attributes (for example by email) in one go with spring rest?

Spring Joining table insert. Skip adding records to other table in join. Persist data only to main and link table

Help me in Entity design with the for following E-R.
Here I need to insert entries into REQUEST table and REQ_TYPE_MAP table. There shouldn't be any entry to TYPE_MAST table.
TYPE_MAST contains master data that are loaded once. I need to map the master data to a request.
But the below approach that I use had adding entries to TYPE_MAST table too. How can I avoid that.
Request Entity
#Entity
#Table(name="REQUEST")
public class Request implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="REQUEST_ID")
private long requestId;
#Column(name="CIVILID")
private Long civilId;
#Column(name="MOBILE_NO")
private Long mobileNo;
#ManyToMany(cascade ={ CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable(name="REQ_TYPE_MAP",
joinColumns = #JoinColumn(name="REQUEST_ID"),
inverseJoinColumns = #JoinColumn(name="TYPE_ID")
)
private Set<MsaDisabScreenRequest> disabilities= new HashSet<MsaDisabScreenRequest>()
/**
getters & setters
equals() & hashCode()
**/
}
Type Mast Entity
#Entity
#Table(name="TYPE_MAST")
public class MsaDisabMaster implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="TYPE_ID")
private long disTypeId;
#Column(name="NAME")
private String name;
/**
getters & setters
equals() & hashCode()
**/
}
Request DTO
public class RequestDto implements Serializable {
private static final long serialVersionUID = 1L;
private long requestId;
private Long civilId;
private Long mobileNo;
private Set<MsaDisabScreenRequestDto> disabilities= new HashSet<MsaDisabScreenRequestDto>()
/**
getters & setters
equals() & hashCode()
**/
}
Type Mast Dto
public class MsaDisabMasterDto implements Serializable {
private static final long serialVersionUID = 1L;
private long disTypeId;
private String name;
/**
getters & setters
equals() & hashCode()
**/
}
Using spring JPA to persist.
#Service code relevant to save(let me know if you required more details).
Service
#SuppressWarnings("all")
public class ReqServiceImpl implements ReqService {
#Autowired
MsaRepository msaRepository;
#Autowired
private OrikaBeanMapper mapper;
#Override
#Transactional(rollbackOn = BusinessException.class)
public long saveScreeningRequest(RequestDto requestDto) throws BusinessException {
try {
// mapping
Request request = mapper.map(requestDto,Request.class);
Request res = reqRepository.save(request);
if (msaDisabScreenRes != null) {
return res.getRequestId();
} else {
//throw exception
}
} catch (DataAccessException e) {
//throw exception
}
}
}
First of all, since MsaDisabMaster is a permanent data, I recommend to make it immutable.
As MsaDisabMaster objects are already persisted then you must remove cascading from its reference in Request.
In your service you should 'attach' all MsaDisabMaster that are contained in RequestDto to the resulted Request. You can do this with getOne method of your MsaDisabMaster repository, something like this:
requestDto.getDisabilities()
.forEach(m -> request.getDisabilities().add(msaDisabMasterRepo.getOne(m.getDisTypeId())));
Then you can save request using save() method of the Request repository.
Please check this example:
https://www.mkyong.com/hibernate/hibernate-many-to-many-relationship-example-annotation/
This should work for you
#ManyToMany(fetch = FetchType.PERSIST, cascade = CascadeType.MERGE)
#JoinTable(name = "REQ_TYPE_MAP",joinColumns = {
#JoinColumn(name = "REQUEST_ID", nullable = false, updatable = false) },
inverseJoinColumns = { #JoinColumn(name = "TYPE_ID",
nullable = false, updatable = false) })

Neo4j RelationshipEntity StackOverflow

I'm having trouble understanding how the #RelationshipEntity works. I've tried following examples, but even though I think I'm following the same pattern as the example, I end up witha stackoverflow, because the Relationship Entity grabs the NodeEntity, which has the RelationshipEntity, and on and on...
My model is:
(:Vendor)-[:BELONGS_TO {active: true, sinceDate: date}]->(:Store)
So my two nodes are Vendor and Store:
#NodeEntity
#Data
public class Vendor {
#GraphId
private Long id;
private Long vendorId;
private String name;
private String address;
#Relationship(type = "OWNS")
private Collection<Inventory> inventory;
#Relationship(type = "BELONGS_TO")
private Collection<Store> store;
}
#NodeEntity
#Data
public class Store {
#GraphId
private Long id;
private Long storeId;
private String name;
private String address;
private String email;
#Relationship(type = "BELONGS_TO", direction = Relationship.INCOMING)
private List<StoreParticipant> storeParticipant;
}
And my RelationshipEntity:
#RelationshipEntity(type = "BELONGS_TO")
#Data
public class StoreParticipant {
#GraphId
private Long id;
#StartNode
private Vendor vendor;
#EndNode
private Store store;
private int count;
private double price;
private boolean negotiable;
private boolean active;
}
I based this off of the Movie example which had (:Person)-[:ACTED_IN]->(:MOVIE) and the acted_in relationship was ROLE
This is happening when I call the repository method findByVendorId
#Repository
public interface VendorRepository extends GraphRepository<Vendor> {
List<Vendor> findByVendorId(Long vendorId);
}
If you're referencing this from both ends, you need to reference the relationship entity, not the node entity directly.
Store looks fine but Vendor contains
#Relationship(type = "BELONGS_TO")
private Collection<Store> store;
when it should be
#Relationship(type = "BELONGS_TO")
private Collection<StoreParticipant> store;

Resources