Entity fetched using findById has all fields set to NULL - java

Entity fetched using Hibernate has all fields set to NULL. How can I avoid this?
This is my Jpa Repository.
#Repository
public interface PolicyRepository extends JpaRepository<Entity, Long>{
Entity findByEntSeqNo(#Param("entSeqNo") long entSeqNo);
}
When debugged I can see that fetched data are inside a field name $$_hibernate_interceptor
This is my entity class
#Entity
#Table(name = "ENTITY_TABLE")
#Lazy(value = false)
public class Entity extends AuditModel {
#Id
#Column(name = "ENT_SEQ_NO")
#GeneratedValue(generator="entitySeq")
#SequenceGenerator(name="entitySeq",sequenceName="\"ENT_SEQ_NO_seq\"", allocationSize=1)
private long entSeqNo;
#Column(name = "ENT_CUSTOMER_CODE")
#NotEmpty(message = "Customer Code is Required.")
private String entCustomerCode;
#Column(name = "ENT_CLAS_CODE")
#NotEmpty(message = "Class Code is Required.")
private String polcClasCode;
#Column(name = "ENT_PROD_CODE")
#NotEmpty(message = "Product Code is Required.")
private String entProdCode;
#Column(name = "ENT_BRANCH_CODE")
#NotEmpty(message = "Branch Code is Required.")
private String entBranchCode;
#Column(name = "ENT_YYY_NO")
#NotEmpty(message = "Yyy Number is Required.")
private String entYyylNo;
#Column(name = "ENT_XX_NO")
private String entXxNo;
#Column(name = "ENT_XXX_NO")
private String entXxxNo;
#Column(name = "ENT_COMMENCEMENT_DATE")
#Temporal(TemporalType.TIMESTAMP)
private Date entCommencementDate;
#Version
#NotNull(message = "Version is Required.")
#Column(name = "VERSION")
private int version;
#Column(name = "ENT_EXPIRY_DATE")
#NotNull(message = "Entity Expiry Date is Required.")
#Temporal(TemporalType.TIMESTAMP)
private Date entExpiryDate;
#Column(name = "ENT_DELIVERY_MODE")
private String entDeliveryMode;
#Column(name = "ENT_COLLECTED_BY")
private String entCollectedBy;
#Column(name = "ENT_COLLECTED_USER_NIC")
private String entCollectedUserNic;
#Column(name = "ENT_COLLECTED_USER_MOBILE")
private String entCollectedUserMobile;
#Column(name = "ENT_COLLECTED_DATE")
#Temporal(TemporalType.TIMESTAMP)
private Date entCollectedDate;
#Column(name = "ENT_POSTED_DATE")
#Temporal(TemporalType.TIMESTAMP)
private Date entPostedDate;
#Column(name = "ENT_POSTED_REF_NO")
private String entPostedRefNo;
#Column(name = "ENT_LANG_CODE")
private String entLangCode;
#Column(name = "ENT_PP1_ID", insertable = false, updatable = false)
private Long entPp1Id;
#Column(name = "ENT_STATUS")
private Short entStatus;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ENT_PP1_ID", referencedColumnName = "ID")
private Pp1 entPp1;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ENT_EPP1_ID", referencedColumnName = "ID")
private Epp1 entEpp1;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx")
private Collection<TaskLog> taskLogColletion;
}
I'm asking this here since I couldn't find the exact cause for this behavior. All the Jpa operations are working fine and this happens only when I try to pick the details from the database. I also tried getOne method and the same problem occurs.

You do not need the method : Entity findByEntSeqNo(#Param("entSeqNo") long entSeqNo); in your jpa interface because entSeqNo is an id of your entity.
So whene you want to get one Entity by id you can just call policyRepository.getOne(the value of entSeqNo) provided by JpaRepository
Or you can use policyRepository.findById(the value of entSeqNo) provided by CrudRepository whitch is basically a superinterface of JpaRepository
Ps: Do no overwrite these methods in you interface.

Related

Update User details endpoint returns 405, "error": "Method Not Allowed",

I'm trying to update the detail of an existing user in the member table but when I tried to test the endpoint using postman it returned a 405, "error": "Method Not Allowed",. I tried to find an existing user by id and update the details so that JPA will automatically save it to the database but it return this error
Member
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
#ManyToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "nationality_id", nullable = false)
private Country nationality;
#ManyToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "country_of_residence_id", nullable = false)
private Country countryOfResidence;
#Temporal(TemporalType.DATE)
#Column(name ="date_of_birth", nullable = false, updatable = false)
private Date dateOfBirth;
#Column(name ="current_job_title", nullable = false)
private String currentJobTitle;
#Column(name = "email_address", nullable = false)
private String emailAddress;
#Column(name ="phone_number", nullable = false)
private String phoneNumber;
#Column(name ="password", nullable = false)
private String password;
#Column(name ="avatar")
private String avatar;
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_on", updatable = false, nullable = false)
private Date createdOn;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated_on", nullable = false)
private Date updatedOn;
Service
public interface UpdateMemberService {
ResponseEntity<Member> getMember(long id, Member member);
}
ServiceImpl
#Service
public class UpdateMemberServiceImpl implements UpdateMemberService {
#Autowired
private UpdateMemberRepository memberRepository;
#Override
public ResponseEntity<Member> getMember(long id, Member member) {
Member getMember = memberRepository.findById(id).get();
getMember.setFirstName(member.getFirstName());
getMember.setLastName(member.getLastName());
getMember.setNationality(member.getNationality());
getMember.setCountryOfResidence(member.getCountryOfResidence());
getMember.setDateOfBirth(member.getDateOfBirth());
getMember.setCurrentJobTitle(member.getCurrentJobTitle());
getMember.setEmailAddress(member.getEmailAddress());
getMember.setPassword(member.getPassword());
getMember.setAvatar(member.getAvatar());
getMember.setActive(member.getActive());
Member updateMember = memberRepository.save(getMember);
return ResponseEntity.ok().body(updateMember);
}
}
Controller
#RestController
#RequestMapping
public class UpdateMemberController {
#Autowired
private UpdateMemberService memberService;
#PutMapping("/update/{id}")
public ResponseEntity<Member> updateDetails(#PathVariable(value = "id") Long id, #RequestBody Member member){
return memberService.getMember(id, member);
}
}
I suggest that you actually debug your code to find out where the failure is.
If, as I suspect, you are not calling the service properly (eg POST instead of PUT), then you won't hit a breakpoint in, say, your controller at all.
If you do hit a breakpoint in your code, look to see where the failure is. If your client calls the service with an id of 1, does a row exist in the database with an id of 1?

delete call stuck for forever in a Many to One Relationship

Trying to run a delete query on a many-one relationship. But sometime it's stuck for a while when the count of row delete is more then ~50.
Repository:
#Repository
public interface TransitItemRepository extends JpaRepository<TransitItemsMapping, UUID> {
#Modifying
#Transactional
#Query(value="delete from TransitItemsMapping t where t.grouping_form_id=:groupingFormId",nativeQuery = true)
void deleteByGroupingFormId(#Param("groupingFormId") UUID groupingFormId);
}
Domain:TransitItemsMapping.java
#Data
#Entity
#Table(name = "TransitItemsMapping")
public class TransitItemsMapping implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "uuid", strategy = "uuid2")
#GeneratedValue(generator = "uuid")
#Column(name = "transit_Item_id",unique = true, nullable = false)
private UUID transitItemId;
#ToString.Exclude
#JsonManagedReference
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "grouping_form_id")
//#OnDelete(action = OnDeleteAction.CASCADE)
private GroupingForm groupingForm;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(referencedColumnName = "dim_Item_ID",name = "item_id")
private Item item;
#Column(name ="item_relationship_id", insertable = false,updatable = false)
private String itemRelationshipId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "item_relationship_id",referencedColumnName = "dim_item_relationship_id")
private VendorFactoryItem vendorFactoryItem;
#Column(name = "edam_id")
private String edamId;
#Column(name = "model_number")
private String modelNumber;
#Column(name = "description")
private String description;
#Column(name = "packaging_details")
private String packagingDetails;
#Column(name = "packaging_method")
private String packagingMethod;
#Column(name = "is_side_stack")
private String isSideStack;
#Column(name = "quantity")
private Integer quantity;
#Column(name = "dimensions")
private String dimensions;
#Column(name = "product_net_weight")
private String productNetWeight;
#Column(name = "plastic_bag_ind")
private String plasticBagInd;
#Column(name = "insertion_order")
private Integer insertionOrder;
#Column(name = "comments")
private String comments;
#Column(name = "item_unique_id")
private String itemUniqueId;
#Column(name = "itm_pak_qty")
private Integer itemPackQuantity;
}
GroupingForm.java
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#Entity
#Table(name = "GroupingForm")
public class GroupingForm implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "uuid", strategy = "uuid2")
#GeneratedValue(generator = "uuid")
#Column(name = "grouping_form_id",unique = true, nullable = false)
private UUID groupingFormId;
#Column(name = "grouping_form_name")
private String groupingFormName;
#Column(name = "vid")
private String vid;
#Column(name = "vendor_name")
private String vendorName;
#Column(name = "hovbu")
private String hovbu;
#Column(name = "fid")
private String fid;
#Column(name = "factory_name")
private String factoryName;
#Column(name = "item_count")
private Integer itemCount;
#CreationTimestamp
#Column(name = "creation_date")
private Timestamp creationDate;
#Column(name = "created_by")
private String createdBy;
#UpdateTimestamp
#Column(name = "modified_date")
private Timestamp modifiedDate;
#Column(name = "modified_by")
private String modifiedBy;
#Column(name = "product_engineer")
private String productEngineer;
#Column(name = "status")
private String status;
#Column(name = "sourcing_type")
private String sourcingType;
#Column(name = "total_comments")
private Integer totalComments;
#Column(name = "factory_name_chinese")
private String factoryNameChinese;
#Column(name = "grouping_form_type")
private String groupingFormType;//to save as Product/transit/Product_transit
#Column(name = "ref_id")
private String refId;
#JsonBackReference
#OneToMany(mappedBy = "groupingForm", cascade = CascadeType.ALL)
private List<ProductItemsMapping> productItems = new ArrayList<>();
#JsonBackReference
#OneToMany(mappedBy = "groupingForm", cascade = CascadeType.ALL)
private List<TransitItemsMapping> transitItems = new ArrayList<>();
#Column(name = "pdf_status")
private String pdfStatus;
public GroupingForm(UUID groupingFormId,String groupingFormName, String vid, String vendorName, String hovbu,
String fid, String factoryName, String status, String sourcingType, Integer totalComments,
Date creationDate, String createdBy, Date modifiedDate, String modifiedBy, String productEngineer,
Integer itemCount, String groupingFormType, String refId, String factoryNameChinese) {
this.groupingFormId = groupingFormId;
this.groupingFormName = groupingFormName;
this.vid = vid;
this.vendorName = vendorName;
this.hovbu = hovbu;
this.fid = fid;
this.factoryName = factoryName;
this.status = status;
this.sourcingType = sourcingType;
this.totalComments = totalComments;
this.creationDate = creationDate!=null?new Timestamp(creationDate.getTime()):null;
this.createdBy = createdBy;
this.modifiedDate = modifiedDate!=null?new Timestamp(modifiedDate.getTime()):null;
this.modifiedBy = modifiedBy;
this.productEngineer = productEngineer;
this.itemCount = itemCount;
this.groupingFormType = groupingFormType;
this.refId = refId;
this.factoryNameChinese = factoryNameChinese;
}
}
Service: methods which already annotated with #Transactional
private void updateTransitItem(GroupingCardsDto groupingCardsDto, GroupingForm groupingForm) {
transitItemRepository.deleteByGroupingFormId(groupingCardsDto.getGroupingFormDto().getGroupingFormId());
groupingFormService.saveTransitItems(groupingCardsDto.getGroupingFormDto(), groupingForm);
}
when I am running eclipse in debug mode then my breakpoint is stuck in delete method. I am using
PostgreSQL 9.6.24 on x86_64-pc-linux-gnu, compiled by Debian clang version 12.0.1, 64-bit
version, and for pool connection Hikari-CP-3.2.0.
And If I let my debug running after long time (~45min) I am getting below error.
marked as broken because of SQLSTATE(08006), ErrorCode(0)\norg.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
Thanks in advance.
There are two possible reasons for this.
Either your delete statement actually takes a really long time, or it is stuck on a lock.
45 min, is certainly a lot for simple delete and could only be expected when you are working on huge amounts of data, like many millions of rows. Use the explain plan to validate that the expected indexes are used.
I consider locks the more likely reason for the problem. You'll need to check what locks are present and where they are coming from. This wiki page about lock monitoring in PostgreSQL seems to be a good starting point.

Spring boot JPA related entity clarification

I have an entity like Process, which will be created by , updated by one user. When I try to apply the filter. I have created the foreign key relationship in the database. Now, when I use the JPA Specification to apply dynamic filter, I am getting exception as
No property CREATED found for type Process!
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id = null;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name = null;
#Column(name = "CREATED_BY", updatable = false)
#JsonProperty("createdBy")
private Long createdBy = null;
#Column(name = "updatedBy", nullable = true)
#JsonProperty("updatedBy")
private Long updatedBy = null;
}
Hence, I Added the entity relationship mapping in the process entity as given below,
Now, I am getting below error. I am new to JPA and hibernate, the relation mapping is very confusing, kindly help.
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id = null;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name = null;
#Column(name = "CREATED_BY", updatable = false)
#JsonProperty("createdBy")
private Long createdBy = null;
#Column(name = "updatedBy", nullable = true)
#JsonProperty("updatedBy")
private Long updatedBy = null;
//newly added below properties so that there will be no error when fetching data
#OneToOne(targetEntity = UserDetails.class, fetch = FetchType.LAZY, mappedBy = "id")
private UserDetails CREATED;
#OneToOne(targetEntity = UserDetails.class, fetch = FetchType.LAZY, mappedBy = "id")
private UserDetails UPDATED;
}
Now, I am getting the below error
Referenced property not a (One|Many)ToOne: com.app.users.details.domain.UserDetails.id in mappedBy of com.app.scenarios.domain.Process.CREATED
Kindly let me know what i am doing wrong. I have a process which can be created by a user and can be updated by a user. In DB, I am having a foreign key relationship for process and userdetails entity.
EDIT
Code to get the filtered data from DB using JPA Specification
Page<process> result = this.processDao.findAll(getprocessGridData(processSearchCondition.getprocessName()), pageRequest);
private static Specification<process> getprocessGridData(String processName) {
return (Specification<process>) (root, query, criteriaBuilder) -> (
criteriaBuilder.like(root.get("name"), processName)
);
}
I guess what you actually want is this:
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name;
#OneToOne(fetch = FetchType.LAZY)
#jOINColumn(name = "CREATED_BY", updatable = false)
private UserDetails createdBy;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "UPDATED_BY", nullable = true)
private UserDetails updatedBy;
}

Spring Architecture circular references and stackoverflows

I have a question about how to avoid circular references and stackoverflows.
I have a User object and another News Object (with a User variable). I need a Comments object (that already has a News variable), but I also need that it has a reference to the User that has created the Comment.
If I create a User variable inside my Comment object I will have circular references and stackoverflows, so I think that I should only incluide a variable like userid in my Comment object.
So it could be that I'm right in my thinking or that I'm doing something wrong to get the stackoverflow errors. What would you do and why? If you can help, that will be great. Thanks.
This is the User...
#Entity
#Table(name = "users")
#PasswordMatch(message = "{register.repeatpassword.mismatch}")
public class SiteUser {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name = "email", unique = true)
#Email(message = "{register.email.invalid}")
#NotBlank(message = "{register.email.invalid}")
private String email;
#Transient
#Size(min = 5, max = 15, message = "{register.password.size}")
private String plainPassword;
#Column(name = "password", length = 60)
private String password;
#Column(name = "enabled")
private Boolean enabled = false;
#NotNull
#Column(name = "firstname", length = 20)
#Size(min = 2, max = 20, message = "{register.firstname.size}")
private String firstname;
#NotNull
#Column(name = "surname", length = 25)
#Size(min = 2, max = 25, message = "{register.surname.size}")
private String surname;
#Transient
private String repeatPassword;
#Column(name = "role", length = 20)
private String role;
public SiteUser() {
}
Here comes the StatusUpdate(you can call it piece of news or article). It has a site user that is the one who has created that article.
#Entity
#Table(name = "status_update")
public class StatusUpdate {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Size(min=5, max=255, message="{addstatus.title.size}")
#Column(name = "title")
private String title;
#Size(min=5, max=5000, message="{addstatus.text.size}")
#Column(name = "text")
private String text;
#Column(name = "added")
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern="yyyy/MM/dd hh:mm:ss")
private Date added;
#OneToOne(targetEntity = SiteUser.class)
#JoinColumn(name="user_id")
private SiteUser siteUser;
#PrePersist
protected void onCreate() {
if (added == null) {
added = new Date();
}
}
public StatusUpdate() {
}
And the Comment which can be done by any registered user, right? As you will notice the Comment has no User object to avoid circular references. And that is the question. How can avoid circular references if Autowired a User
#Entity
#Table(name = "comments")
public class Comment {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name = "statusupdateid")
private StatusUpdate statusUpdate;
#Column(name = "commenttext")
private String commenttext;
#Column(name = "commentdate")
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "yyyy/MM/dd hh:mm:ss")
private Date commentdate;
#Column(name = "userid")
private Long userid;
public Comment() {
}

update all fields of an entity in jpa

I have tow entity User and Project that they have "one to many" relationship and I want to find the User then find the specific Project that belong to User and then update it, but I can't.
framework Struts2 + Hibernate .
#Entity (name = "User")
#Table (name = "users")
public class User implements Serializable{
#Id
#Column (name = "user_id", columnDefinition = "number")
#SequenceGenerator(name = "seq", sequenceName = "gen")
#GeneratedValue(strategy = GenerationType.AUTO, generator = "seq")
private int id;
#Basic
#Column(name = "user_name", columnDefinition = "nvarchar2(20)")
private String userName;
#Basic
#Column(name = "password", columnDefinition ="nvarchar2(20)")
private String password;
#Basic
#Column(name = "create_date",columnDefinition = "date")
private Date creation_date;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private List<Project> projectses;
public List<Project> getProjectses() {
return projectses;
}
public void setProjectses(List<Project> projectses) {
this.projectses = projectses;
}
and Project entity
#Entity(name = "Project")
#Table(name = "project")
public class Project implements Serializable {
#Id
#Column(name = "project_id" , columnDefinition = "number")
#SequenceGenerator(name = "projectSeq", sequenceName = "projectGen")
#GeneratedValue(strategy = GenerationType.AUTO,generator = "projectSeq")
private int projectId;
#Basic
#Column(name = "project_name" , columnDefinition = "nvarchar2(20)")
private String projectName;
#Basic
#Column(name = "project_description" , columnDefinition = nvarchar2(20)")
private String projectDescription;
#Basic
#Column(name = "start_date",columnDefinition = "date")
private Date startDate;
#Basic
#Column(name = "due_date",columnDefinition = "date")
private Date dueDate;
#Basic
#Column(name = "project_status",columnDefinition = "nvarchar2(20)")
private String projectStatus;
#Basic
#Column(name = "project_amount",columnDefinition = "number(8)")
private int projectAmount;
Three corrections come in mind, that may make your code behave well:
Use EntityManager#find() instead of HQL to lookup entity by id;
Use only one of #Basic or #Column (I'd prefer #Column), there is no need to use both for a single element;
If error is "value is too long for column", maybe it is time to check if some of Project elements are longer than 20 chars defined in columnDefinition?
Check length of string elements in Project entities, and if there are some longer than 20 characters, say, 500, modify columnDefinition for those elements, e. g.:
#Column(name = "project_description", columnDefinition = "nvarchar2(500)")
private String projectDescription;
I also suggest to drop tables after such modifications (to allow JPA create new according to new definitions) or manually modify their definitions in DB.
User u = (User)entityManager.createQuery(SELECT u FROM User u JOIN FETCH u.Project where u.id = :id).setParameter("id",your_userId).uniqueResult();
Get The user object , you will get it with the set of projects associated with that user
update the data you want : -
List<Project> userProjects = u.getProjectses();
for(int i = 0 ; i < userProjects.size() ; i++){
Project p = userProjects.get(i);
entityManager.getTransaction().begin();
p.setProjectName("test");
entityManager.merge(p);
entityManager.getTransaction().commit();
}

Categories