JPA won't save an entity correctly unless the references to other entities are set - jpa

If I save this entity using JPA repository with a new defaultAssetId, it will only update the defaultAsssetId to the new value if I set defaultAsset as well. I want to be able to save without setting defaultAsset.
Same problem applies to taskType and assetRole.
package au.com.polonious.conf.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
#Entity
public class TaskTypeAssetRole implements Serializable {
#GenericGenerator(name="tasktypeassetroleidseq",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
#Parameter(name = "sequence_name", value = "tasktypeassetroleidseq"),
#Parameter(name = "initial_value", value = "1"),
#Parameter(name = "increment_size", value = "1")
})
#Id
#GeneratedValue(generator = "tasktypeassetroleidseq")
private Long id;
#Column(insertable = false, updatable=false)
private Long taskTypeId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="tasktypeid")
private TaskType taskType;
#Column(insertable = false, updatable=false)
private Long assetRoleId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="assetRoleId")
private Role assetRole;
#Column(insertable = false, updatable=false)
private Long defaultAssetId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="defaultassetid")
private Asset defaultAsset;
private Date startDate;
private Date endDate;
private String notes;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getTaskTypeId() {
return taskTypeId;
}
public void setTaskTypeId(Long taskTypeId) {
this.taskTypeId = taskTypeId;
}
public TaskType getTaskType() {
return taskType;
}
public void setTaskType(TaskType taskType) {
this.taskType = taskType;
}
public Long getAssetRoleId() {
return assetRoleId;
}
public void setAssetRoleId(Long assetRoleId) {
this.assetRoleId = assetRoleId;
}
public Role getAssetRole() {
return assetRole;
}
public void setAssetRole(Role assetRole) {
this.assetRole = assetRole;
}
public Long getDefaultAssetId() {
return defaultAssetId;
}
public void setDefaultAssetId(Long defaultAssetId) {
this.defaultAssetId = defaultAssetId;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
}
I tried saving a taskTypeAssetRole with a new defaultAssedId without setting defaultAsset and I expected the defaultAssedId for that entry in the database to be updated.
What ended up happening was defaultAssetId didn't change although everything else in the entry did update successfully and there were no errors.

Your mapping is inherently broken. The column defaultassetiId is mapped to two different values: the field defaultAssetId and to the id of defaultAsset.
You should remove the defaultAssetId because this construct might break on any update of your JPA provider.
You can use references instead of full entities to set the reference values without loading entities from the database. See https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html#getReferenceById-ID-
If you don't follow this advice you should remove updatable=false if you want to update a field.

Related

Spring JpaRepository save causes 100s of selects to be generated

Im getting very strange error when I call save on a JpaRepository.
The code seems trivial so i can only think its something to do with configuration.
Basically I call a findBy method on the repository, this returns a list of dao objects exactly as expected, I go through this list setting a timestamp then calling save() on each dao, as soon as the first save is called the log is filled with hundreds of identical select statements, selecting on the dao I'm just trying to save until eventually there is a stack overflow.
What could cause this ???
(note originally I called saveAll() on the list of dao objects - this, unsurprisingly has the same error )
public void triggerDeletion() {
ZonedDateTime expiryDate = ZonedDateTime.now().minus(daysAfterExpiry);
// Get list of conversations to delete
List<ConversationDao> conversationDaoList = conversationDatabaseService.retrieveExpiredConversations(expiryDate);
// Mark each conversation as deleted by setting its deletion timestamp to now.
conversationDaoList.stream().forEach(conversation->delete(conversation));
}
public void delete(ConversationDao conversationDao){
conversationDao.setDeletionTimestamp(new Timestamp(System.currentTimeMillis()));
conversationDatabaseService.save( conversationDao ); <------ This generates 100s of select statements.
}
...
// ConversationDatabaseService Interface
////////////////////////////////////////
public interface ConversationDatabaseService {
void save(ConversationDao conversationDao);
}
...
// Conversation DatabaseService Class
/////////////////////////////////////
#Service
public class ConversationDatabaseServiceImpl implements ConversationDatabaseService {
private final ConversationRepository conversationRepository;
public void save(ConversationDao conversationDao) {
conversationRepository.saveAndFlush(conversationDao); // Just save has also been tried.
}
}
...
// ConversationRepository interface
///////////////////////////////////
public interface ConversationRepository extends JpaRepository<ConversationDao, String> {
List<ConversationDao> findByExpiryDateLessThanAndDeletionTimestampIsNull(Timestamp expiryDate);
}
...
// ConversationDao
//////////////////////////////////
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.UpdateTimestamp;
#Entity
#Table(name = "DOCX_CONVERSATION")
public class ConversationDao {
#Id
#GeneratedValue(generator = "uuid2")
#GenericGenerator(name = "uuid2",
strategy = "uuid2")
#Column(name = "CONVERSATION_ID",
columnDefinition = "char")
private String conversationId;
#Column(name = "PROCESS_CODE")
private String processCode;
#Column(name = "PROFILE_ID",
columnDefinition = "char")
private String profileId;
#Column(name = "REMINDER_EMAIL_SENT",
columnDefinition = "char")
private String reminderEmailSent;
#Column(name = "EXPIRY_DATE")
private Date expiryDate;
#Column(name = "DELETION_TIMESTAMP")
private Timestamp deletionTimestamp;
#Column(name = "LAST_LOGIN_TIMESTAMP")
private Timestamp lastLoginTimestamp;
#Column(name = "CREATED_USER_ID",
columnDefinition = "char")
private String colleagueId;
#Column(name = "CREATED_TIMESTAMP",
updatable = false)
#CreationTimestamp
private Timestamp createdTimestamp;
#Column(name = "LAST_UPDATED_USER_ID",
columnDefinition = "char")
private String lastUpdatedUserId;
#Column(name = "LAST_UPDATED_TIMESTAMP")
#UpdateTimestamp
private Timestamp lastUpdatedTimestamp;
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<MessageDetailDao> messageDetailDaoSet = new HashSet<>();
#OneToMany(mappedBy = "fileDetailId.conversation",
cascade = CascadeType.ALL)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<ParameterDao> parameterDaoSet = new HashSet<>();
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<NotificationDao> notificationDaoSet = new HashSet<>();
public ConversationDao() {
}
public ConversationDao(String processCode, Date expiryDate,
String colleagueId, String lastUpdatedUserId) {
this.processCode = processCode;
this.reminderEmailSent = "N";
this.expiryDate = expiryDate;
this.colleagueId = colleagueId;
this.lastUpdatedUserId = lastUpdatedUserId;
}
public String getConversationId() {
return conversationId;
}
public void setConversationId(String conversationId) {
this.conversationId = conversationId;
}
public String getProcessCode() {
return processCode;
}
public void setProcessCode(String processCode) {
this.processCode = processCode;
}
public String getProfileId() {
return profileId;
}
public void setProfileId(String profileId) {
this.profileId = profileId;
}
public String getReminderEmailSent() {
return reminderEmailSent;
}
public void setReminderEmailSent(String reminderEmailSent) {
this.reminderEmailSent = reminderEmailSent;
}
public Date getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(Date expiryDate) {
this.expiryDate = expiryDate;
}
public Timestamp getDeletionTimestamp() {
return deletionTimestamp;
}
public void setDeletionTimestamp(Timestamp deletionTimestamp) {
this.deletionTimestamp = deletionTimestamp;
}
public Timestamp getLastLoginTimestamp() {
return lastLoginTimestamp;
}
public void setLastLoginTimestamp(Timestamp lastLoginTimestamp) {
this.lastLoginTimestamp = lastLoginTimestamp;
}
public String getColleagueId() {
return colleagueId.trim();
}
public void setColleagueId(String colleagueId) {
this.colleagueId = colleagueId;
}
public Timestamp getCreatedTimestamp() {
return createdTimestamp;
}
public void setCreatedTimestamp(Timestamp createdTimestamp) {
this.createdTimestamp = createdTimestamp;
}
public String getLastUpdatedUserId() {
return lastUpdatedUserId;
}
public void setLastUpdatedUserId(String lastUpdatedUserId) {
this.lastUpdatedUserId = lastUpdatedUserId;
}
public Timestamp getLastUpdatedTimestamp() {
return lastUpdatedTimestamp;
}
public void setLastUpdatedTimestamp(Timestamp lastUpdatedTimestamp) {
this.lastUpdatedTimestamp = lastUpdatedTimestamp;
}
public void addMessageDetailDao(MessageDetailDao messageDetailDao) {
messageDetailDaoSet.add(messageDetailDao);
messageDetailDao.setConversation(this);
}
public Set<MessageDetailDao> getMessageDetailDao() {
return messageDetailDaoSet;
}
public void addFileDetailDao(FileDetailDao fileDetailDao) {
fileDetailDaoSet.add(fileDetailDao);
fileDetailDao.getId().setConversation(this);
}
public Set<FileDetailDao> getFileDetailDao() {
return fileDetailDaoSet;
}
public void addParameterDao(ParameterDao parameterDao) {
parameterDaoSet.add(parameterDao);
parameterDao.setConversation(this);
}
public Set<ParameterDao> getParameterDao() {
return parameterDaoSet;
}
public void addNotificationDao(NotificationDao notificationDao) {
notificationDaoSet.add(notificationDao);
notificationDao.setConversation(this);
}
public Set<NotificationDao> getNotificationDao() {
return notificationDaoSet;
}
}
}
This generates these same select statements 100s of times before blowing the stack :-
1TS="20190411.075004.028" 4MSG="binding parameter [1] as [VARCHAR] - [6df49d6f-216b-460d-9282-2d25c098f9fe]" 1EVC="TRACE" 2CLS="BasicBinder"
1TS="20190411.075004.065" 4MSG="extracted value ([convers16_10_0_] : [VARCHAR]) - [6df49d6f-216b-460d-9282-2d25c098f9fe]" 1EVC="TRACE" 2CLS="BasicExtractor"
1TS="20190411.075004.069" 4MSG="extracted value ([file_met1_10_0_] : [VARCHAR]) - [4E90FD20-FC59-41B8-BF8E-88B7D682A87C]" 1EVC="TRACE" 2CLS="BasicExtractor"
1TS="20190411.075004.074" 4MSG="select conversati0_.conversation_id as conversa1_5_1_, conversati0_.created_user_id as created_2_5_1_, conversati0_.created_timestamp as created_3_5_1_, conversati0_.deletion_timestamp as deletion4_5_1_, conversati0_.expiry_date as expiry_d5_5_1_, conversati0_.last_login_timestamp as last_log6_5_1_, conversati0_.last_updated_timestamp as last_upd7_5_1_, conversati0_.last_updated_user_id as last_upd8_5_1_, conversati0_.process_code as process_9_5_1_, conversati0_.profile_id as profile10_5_1_, conversati0_.reminder_email_sent as reminde11_5_1_, filedetail1_.conversation_id as convers16_10_3_, filedetail1_.file_metadata_id as file_met1_10_3_, filedetail1_.conversation_id as convers16_10_0_, filedetail1_.file_metadata_id as file_met1_10_0_, filedetail1_.application_id as applicat2_10_0_, filedetail1_.case_id as case_id3_10_0_, filedetail1_.created_user_id as created_4_10_0_, filedetail1_.content_type as content_5_10_0_, filedetail1_.created_by as created_6_10_0_, filedetail1_.created_timestamp as created_7_10_0_, filedetail1_.document_code as document8_10_0_, filedetail1_.document_owner as document9_10_0_, filedetail1_.document_repository_state as documen10_10_0_, filedetail1_.file_name as file_na11_10_0_, filedetail1_.file_size_bytes as file_si12_10_0_, filedetail1_.file_state as file_st13_10_0_, filedetail1_.file_version as file_ve14_10_0_, filedetail1_.updated_by as updated15_10_0_ from docx_conversation conversati0_ left outer join docx_file_detail filedetail1_ on conversati0_.conversation_id=filedetail1_.conversation_id where conversati0_.conversation_id=?" 1EVC="DEBUG" 2CLS="SQL"
What is going on ??
Some more information, the cause is definitely connected to this part of the dao :-
#OneToMany(mappedBy = "fileDetailId.conversation",cascade = CascadeType.ALL)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();
The FileDetailDao contains an embedded reference to a FileDetailId
#EmbeddedId
private FileDetailId fileDetailId;
And this FileDetailId contains a reference to the conversationId of the join :-
#Embeddable
public class FileDetailId implements Serializable {
#Column(name = "FILE_METADATA_ID", columnDefinition = "char")
private String fileMetadataId;
#ManyToOne
#JoinColumn(name = "CONVERSATION_ID")
private ConversationDao conversation;
//etc
}
Im not sure why but if I change the cascade type to REMOVE it works ok....
#OneToMany(mappedBy = "fileDetailId.conversation",cascade = CascadeType.REMOVE)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();

Why does id of child entity return 0 in response message in EclipseLink?

I'm using a One-To-One association between my Member and MemberRoles tables. I wanted them to share the same id as PK and FK in the database and did it. But I've got another problem. When I insert a Member, a MemberRole record is being inserted with it and Member record has the correct id in return response but MemberRole id is incorrect. It returns 0 like this:
{
"result": "Bulk user member saving is successfull. Members' informations are:",
"memberList": [
{
"id": 2,
"firstName": "Michael",
"lastName": "Schumacher",
"email": "ilkay.gune2l#kod5.org",
"enabled": false,
"memberLanguageCode": "tr",
"roleOfMember": {
"id": 0,
"email": "ilkay.gune2l#kod5.org",
"role": "ROLE_USER"
}
}
]
}
My Member Entity Class:
package com.ilkaygunel.entities;
import java.time.LocalDateTime;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
#Entity
#JsonInclude(Include.NON_NULL)
#NamedQueries({ #NamedQuery(name = "Member.findAll", query = "select m from Member m"),
#NamedQuery(name = "Member.findByFirstName", query = "select m from Member m where m.firstName =:firstName"),
#NamedQuery(name = "Member.findPasswordOfMember", query = "select m.password from Member m where m.id =:id"),
#NamedQuery(name = "Member.findByActivationToken", query = "select m from Member m where m.activationToken =:activationToken"),
#NamedQuery(name = "Member.findByEmail", query = "select m from Member m where m.email =:email") })
#Table(name = "MEMBER")
public class Member {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "MEMBER_ID")
private long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String lastName;
#Column(nullable = false, updatable = false)
private String email;
#Column(nullable = false, updatable = false)
private boolean enabled;
#Column(nullable = false)
private String password;
#Column(nullable = false)
private String memberLanguageCode;
#Column(updatable = false)
#JsonIgnore
private String activationToken;
#Column(updatable = false)
#JsonIgnore
private LocalDateTime activationTokenExpDate;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "member", optional = false)
#PrimaryKeyJoinColumn(name = "MEMBER_ID")
private MemberRoles roleOfMember;
#Override
public String toString() {
return String.format("Member [id=%d, firstName='%s', lastName='%s', email='%s']", id, firstName, lastName,
email);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
if (null != roleOfMember) {
roleOfMember.setId(id);
}
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public MemberRoles getRoleOfMember() {
return roleOfMember;
}
public void setRoleOfMember(MemberRoles roleOfMember) {
this.roleOfMember = roleOfMember;
}
public String getActivationToken() {
return activationToken;
}
public void setActivationToken(String activationToken) {
this.activationToken = activationToken;
}
public LocalDateTime getActivationTokenExpDate() {
return activationTokenExpDate;
}
public void setActivationTokenExpDate(LocalDateTime activationTokenExpDate) {
this.activationTokenExpDate = activationTokenExpDate;
}
public String getMemberLanguageCode() {
return memberLanguageCode;
}
public void setMemberLanguageCode(String memberLanguageCode) {
this.memberLanguageCode = memberLanguageCode;
}
}
And my MemberRoles Entity class:
package com.ilkaygunel.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapsId;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#NamedQueries({
#NamedQuery(name = "MemberRoles.findByEmail", query = "select mr from MemberRoles mr where mr.email = :email") })
#Table(name = "MEMBERROLES")
public class MemberRoles {
#Id
#Column(name = "MEMBERROLES_ID")
private long id;
private String email;
private String role;
#MapsId
#OneToOne(optional = false)
#JoinColumn(name = "MEMBERROLES_ID", unique = true, nullable = false, updatable = false)
#JsonIgnore
private Member member;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
}
When I inserted a Member record, I check it on the database and see that Member and MemberRoles record have the same id. But why does MemberRoles area in response message has got id as 0?
My MemberSaveService class like this:
package com.ilkaygunel.service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.MessagingException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.ilkaygunel.constants.ConstantFields;
import com.ilkaygunel.entities.Member;
import com.ilkaygunel.entities.MemberRoles;
import com.ilkaygunel.exception.CustomException;
import com.ilkaygunel.exception.ErrorCodes;
import com.ilkaygunel.pojo.MemberOperationPojo;
#Service
public class MemberSaveService extends BaseService {
public MemberOperationPojo addUserMember(List<Member> memberList) {
return addBulkMember(memberList, ConstantFields.ROLE_USER.getConstantField());
}
public MemberOperationPojo addAdminMember(List<Member> memberList) {
return addBulkMember(memberList, ConstantFields.ROLE_ADMIN.getConstantField());
}
public MemberOperationPojo addBulkMember(List<Member> memberList, String role) {
Logger LOGGER = loggingUtil.getLoggerForMemberSaving(this.getClass());
LOGGER.log(Level.INFO, resourceBundleMessageManager.getValueOfProperty(role + "_bulkMemberAddingMethod", "en"));
MemberOperationPojo memberOperationPojo = new MemberOperationPojo();
List<Member> savedMemberList = new ArrayList<>();
try {
memberUtil.checkEmailAddressAndLanguageOnMemberList(memberList, LOGGER);
for (Member member : memberList) {
addOneMember(member, role, LOGGER);
savedMemberList.add(member);
}
memberOperationPojo.setResult(
resourceBundleMessageManager.getValueOfProperty(role + "_bulkMemberAddingSuccessfull", "en"));
memberOperationPojo.setMemberList(memberUtil.removeFieldsFromReturningMember(savedMemberList));
LOGGER.log(Level.INFO,
resourceBundleMessageManager.getValueOfProperty(role + "_bulkMemberAddingSuccessfull", "en")
+ memberList);
} catch (CustomException customException) {
LOGGER.log(Level.SEVERE,
resourceBundleMessageManager.getValueOfProperty(role + "_bulkMemberAddingFaled", "en")
+ customException.getErrorCode() + " " + customException.getErrorMessage());
memberOperationPojo.setErrorCode(customException.getErrorCode());
memberOperationPojo.setResult(customException.getErrorMessage());
} catch (Exception e) {
LOGGER.log(Level.SEVERE,
resourceBundleMessageManager.getValueOfProperty(role + "_bulkMemberAddingFaled", "en")
+ e.getMessage());
memberOperationPojo.setErrorCode(ErrorCodes.ERROR_10.getErrorCode());
memberOperationPojo.setResult(e.getMessage());
}
return memberOperationPojo;
}
private void addOneMember(Member member, String role, Logger LOGGER) throws MessagingException {
MemberOperationPojo memberOperationPojo = new MemberOperationPojo();
LOGGER.log(Level.INFO, resourceBundleMessageManager.getValueOfProperty(role + "_memberAddingMethod",
member.getMemberLanguageCode()));
member.setPassword(getHashedPassword(member.getPassword()));
member.setEnabled(false);
addMemberRolesObject(role, member);
addActivationToken(member);
memberFacade.create(member);
// mailUtil.sendActivationMail(member.getEmail(), member.getActivationToken());
memberOperationPojo.setResult(resourceBundleMessageManager.getValueOfProperty(role + "_memberAddingSuccessfull",
member.getMemberLanguageCode()));
LOGGER.log(Level.INFO, resourceBundleMessageManager.getValueOfProperty(role + "_memberAddingSuccessfull",
member.getMemberLanguageCode()) + member);
}
private String getHashedPassword(String rawPassword) {
return new BCryptPasswordEncoder().encode(rawPassword);
}
private void addMemberRolesObject(String role, Member member) {
MemberRoles rolesOfMember = new MemberRoles();
rolesOfMember.setRole(role);
rolesOfMember.setEmail(member.getEmail());
rolesOfMember.setMember(member);
member.setRoleOfMember(rolesOfMember);
}
private void addActivationToken(Member member) {
String activationToken = UUID.randomUUID().toString();
member.setActivationToken(activationToken);
LocalDateTime activationTokenExpDate = LocalDateTime.now().plusDays(1);
// LocalDateTime activationTokenExpDate = LocalDateTime.now();//Use for expire
// date test!
member.setActivationTokenExpDate(activationTokenExpDate);
}
}
My Web Service End Point Class like this:
package com.ilkaygunel.restservice;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.ilkaygunel.entities.Member;
import com.ilkaygunel.pojo.MemberOperationPojo;
import com.ilkaygunel.service.MemberSaveService;
#RestController
#RequestMapping("/memberPostWebServiceEndPoint")
public class MemberSaveWebServiceEndPoint {
#Autowired
private MemberSaveService memberSaveService;
#RequestMapping(value = "/saveUserMember", method = RequestMethod.POST)
public ResponseEntity<MemberOperationPojo> saveUserMember(#RequestBody List<Member> memberList) {
MemberOperationPojo memberOperationPojo = memberSaveService.addUserMember(memberList);
return new ResponseEntity<MemberOperationPojo>(memberOperationPojo, HttpStatus.OK);
}
#RequestMapping(value = "/saveAdminMember", method = RequestMethod.POST)
public ResponseEntity<MemberOperationPojo> saveAdminMember(#RequestBody List<Member> memberList) {
MemberOperationPojo memberOperationPojo = memberSaveService.addAdminMember(memberList);
return new ResponseEntity<MemberOperationPojo>(memberOperationPojo, HttpStatus.OK);
}
}

Neo4j Springboot SpringData restful example not complete without relationship entity

I am using the springio accessing-neo4j-data-rest example which has the relationship as part of the Person class and really doesn't show the advantage of Neo4j. I tried creating a Family relationship entity, but can't create a relationship using a restful service with Springboot and port 8080.
My service works and creates the relationship using http://localhost:7474/db/data/node/67/relationships
Shouldn't I be able to do this (where 66 and 67 are existing Person entities):
POST to http://localhost:8080/people/67/family
{
"to" : "http://localhost:8080/people/66",
"type" : "RELATED_TO"
}
I get the error:
{
"timestamp": 1486948326367,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/people/67/family"
}
Person.java
package hello;
import java.util.HashSet;
import java.util.Set;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
#NodeEntity
public class Person {
#GraphId public Long id;
private String firstName;
private String lastName;
#Relationship(type = Family.TYPE, direction = Relationship.UNDIRECTED)
private Set<Family> family = new HashSet<Family>();
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Set<Family> getFamily() {
return family;
}
public void addFamily(Family f) {
family.add(f);
}
public void addFamily(Person target, String association) {
this.family.add(new Family(this, target, association));
}
public void addFamily(Person target) {
this.family.add(new Family(this, target));
}
}
Family.java
package hello;
import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;
#RelationshipEntity(type = Family.TYPE)
public class Family {
public static final String TYPE = "RELATED_TO";
#GraphId
private Long id;
#Property
private String association;
#StartNode
private Person p1;
#EndNode
private Person p2;
public Family() {
}
public Family(Person first, Person second) {
this.p1 = first;
this.p2 = second;
}
public Family(Person first, Person second, String assoc) {
this.p1 = first;
this.p2 = second;
association = assoc;
}
public Long getId() {
return id;
}
public Person getFirst() {
return p1;
}
public Person getSecond() {
return p2;
}
public String getAssociation() {
return association;
}
public void setAssociation(String association) {
this.association = association;
}
}
PersonRepository.java
package hello;
import java.util.List;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
List<Person> findByFirstName(#Param("name") String name);
}
FamilyRepository .java
package hello;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource(collectionResourceRel = "family", path = "family") // what should go here????
public interface FamilyRepository extends GraphRepository<Family> {
// //creates a get - need a post
// #Query("MATCH (a:Traveler),(b:Traveler) WHERE a.lastName = {from} AND b.lastName = {to} CREATE (a)-[r:RELATED_TO]->(b) RETURN r")
// void worksWith(#Param("to") String to);
}
Edited:2-19-2017 - Getting closer. I needed a controller - something like this:
#RestController
public class FamilyController {
...
#RequestMapping(value = "/people/{id}/family", method = RequestMethod.POST, consumes = APPLICATION_JSON, produces = APPLICATION_JSON)
#ResponseStatus(value = HttpStatus.ACCEPTED)
#ResponseBody
Family addFamily(#RequestBody Family f, #PathVariable(value = "id") String id) {

Add data to database adding data to join tables

I'm working in a project and I'm looking to add data to the database, to two join tables.
My parent:
package entity;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the artiste database table.
*
*/
#Entity
#NamedQuery(name="Artiste.findAll", query="SELECT a FROM Artiste a")
public class Artiste implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_artiste")
private int idArtiste;
#Column(name="a_category")
private String aCategory;
#Column(name="a_name")
private String aName;
private String date;
//bi-directional many-to-one association to Seat
#ManyToOne
#JoinColumn(name="id_seat")
private Seat seat;
public Artiste() {
}
public int getIdArtiste() {
return this.idArtiste;
}
public void setIdArtiste(int idArtiste) {
this.idArtiste = idArtiste;
}
public String getACategory() {
return this.aCategory;
}
public void setACategory(String aCategory) {
this.aCategory = aCategory;
}
public String getAName() {
return this.aName;
}
public void setAName(String aName) {
this.aName = aName;
}
public String getDate() {
return this.date;
}
public void setDate(String date) {
this.date = date;
}
public Seat getSeat() {
return this.seat;
}
public void setSeat(Seat seat) {
this.seat = seat;
}
}
My child:
package entity;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the seat database table.
*
*/
#Entity
#NamedQuery(name="Seat.findAll", query="SELECT s FROM Seat s")
public class Seat implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_seat")
private int idSeat;
private String seat_CA;
private String seat_CB;
private String seat_CC;
private String seat_CD;
//bi-directional many-to-one association to Artiste
#OneToMany(mappedBy="seat")
private List<Artiste> artistes;
public Seat() {
}
public int getIdSeat() {
return this.idSeat;
}
public void setIdSeat(int idSeat) {
this.idSeat = idSeat;
}
public String getSeat_CA() {
return this.seat_CA;
}
public void setSeat_CA(String seat_CA) {
this.seat_CA = seat_CA;
}
public String getSeat_CB() {
return this.seat_CB;
}
public void setSeat_CB(String seat_CB) {
this.seat_CB = seat_CB;
}
public String getSeat_CC() {
return this.seat_CC;
}
public void setSeat_CC(String seat_CC) {
this.seat_CC = seat_CC;
}
public String getSeat_CD() {
return this.seat_CD;
}
public void setSeat_CD(String seat_CD) {
this.seat_CD = seat_CD;
}
public List<Artiste> getArtistes() {
return this.artistes;
}
public void setArtistes(List<Artiste> artistes) {
this.artistes = artistes;
}
public Artiste addArtiste(Artiste artiste) {
getArtistes().add(artiste);
artiste.setSeat(this);
return artiste;
}
public Artiste removeArtiste(Artiste artiste) {
getArtistes().remove(artiste);
artiste.setSeat(null);
return artiste;
}
}
My client:
Artiste a= new Artiste();
Seat b = new Seat();
b.setSeat_CA(request.getParameter("w"));
b.setSeat_CB(request.getParameter("x"));
b.setSeat_CD(request.getParameter("y"));
b.setSeat_CC(request.getParameter("z"));
a.setIdArtiste(b.getIdSeat());
seatFacade.create(b);
a.setAName(request.getParameter("a_name"));
a.setACategory(request.getParameter("a_category"));
a.setDate(request.getParameter("date"));
artisteFacade.create(a);
And I create the FACADE for each one.
Now I can add data but i need also the program add the FOREIGN KEY.
You don't need to get the foreign key, JPA is do every thing, so you should just make it in the right way, so you entities should look like this:
Artiste Entity
#ManyToOne
#JoinColumn(name="id_seat")
private Seat seat;
Seat Entity
#OneToMany(mappedBy="seat", cascade = CascadeType.ALL)
private List<Artiste> artistes = new ArrayList<>();
Your code should look like this:
Artiste a= new Artiste();
Seat b = new Seat();
b.setSeat_CA(request.getParameter("w"));
b.setSeat_CB(request.getParameter("x"));
b.setSeat_CD(request.getParameter("y"));
b.setSeat_CC(request.getParameter("z"));
a.setAName(request.getParameter("a_name"));
a.setACategory(request.getParameter("a_category"));
a.setDate(request.getParameter("date"));
//add this the Article to the list of Seat like this.
b.getArtistes().add(a);
//a.setIdArtiste(b.getIdSeat()); you don't need this
//artisteFacade.create(a); you dont need this also
//set the Seal to your article
a.setSeat(b);
seatFacade.create(b);
So when you persist the Seat the list of articles will persist automaticlly.
This will help you.
You can learn more here : JPA #ManyToOne with CascadeType.ALL

how to make #id fields editable in forge crud?

I want to generate a crud for an entity with an editable primary key but forge doesnt generate the #id field this is my entity note that the id field is an string it is not a an auto increment id field.
package com.samples.model;
// Generated 14/01/2013 11:23:23 AM by Hibernate Tools 3.4.0.CR1
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* Pais generated by hbm2java
*/
#Entity
#Table(name = "pais", schema = "public")
public class Pais implements java.io.Serializable
{
/**
*
*/
private static final long serialVersionUID = -8369022633869576848L;
private String paisId;
private Date fechaRegistro;
private String descripcion;
private short estatus;
private Set<Estado> estados = new HashSet<Estado>(0);
public Pais()
{
}
public Pais(String paisId, Date fechaRegistro, short estatus)
{
this.paisId = paisId;
this.fechaRegistro = fechaRegistro;
this.estatus = estatus;
}
public Pais(String paisId, Date fechaRegistro, String descripcion, short estatus, Set<Estado> estados)
{
this.paisId = paisId;
this.fechaRegistro = fechaRegistro;
this.descripcion = descripcion;
this.estatus = estatus;
this.estados = estados;
}
#Id
#Column(name = "pais_id", unique = true, nullable = false, length = 5)
public String getPaisId()
{
return this.paisId;
}
public void setPaisId(String paisId)
{
this.paisId = paisId;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "fecha_registro", nullable = false, length = 29)
public Date getFechaRegistro()
{
return this.fechaRegistro;
}
public void setFechaRegistro(Date fechaRegistro)
{
this.fechaRegistro = fechaRegistro;
}
#Column(name = "descripcion", length = 30)
public String getDescripcion()
{
return this.descripcion;
}
public void setDescripcion(String descripcion)
{
this.descripcion = descripcion;
}
#Column(name = "estatus", nullable = false)
public short getEstatus()
{
return this.estatus;
}
public void setEstatus(short estatus)
{
this.estatus = estatus;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pais")
public Set<Estado> getEstados()
{
return this.estados;
}
public void setEstados(Set<Estado> estados)
{
this.estados = estados;
}
}
JBoss Forge uses Metawidget for its UI generation. So to accomplish this you must modify Forge's metawidget.xml configuration file.
Forge actually has 3 Metawidget configuration files: metawidget-entity.xml for viewing/editing screens, metawidget-search.xml for search filters, and metawidget-qbe.xml for generating Java code.
For your purposes, you need to modify metawidget-entity.xml. Specifically you must find the JpaInspector entry...
<jpaInspector xmlns="java:org.metawidget.inspector.jpa" config="JpaInspectorConfig">
...and add a child node...
<hideIds><boolean>false</boolean></hideIds>
That bit should be straightforward. However actually getting your modified metawidget-entity.xml back into Forge is clumsy. At the moment the easiest way is probably to unzip and modify the forge-scaffold-faces.jar itself. Hopefully this will be made cleaner in a future Forge release.