We have a class User
, which has a field isMigrated
which is 0
by default. Now in the service layer, we are trying to update the user's status
(another attribute). So these are the steps
- We fetch the user by his ID (Primary key).
- We set the new status.
- We call the
save
method in the respective repository for that particular user.
Now the problem is that the column that corresponds to isMigrated
, which is currently having a value of 1
is also getting updated to 0
. We have clearly not updated that attribute and so we came to a conclusion that it is the default value that is going to the DB during updation, but how is that possible?
We tried to check some other information about JPA: update only specific fields but wasn't helpful in this case. We had to go with native query to fix this problem.
Entity class
@Entity
@Table(name = "USER_TABLE")
public class User implements Serializable {
// other attributes
@Column(name = "USER_STATUS")
private int status;
// [1 = migrated, 0 = new (default)]
@Column(name = "IS_MIGRATED")
private int isMigrated = 0;
// getters and setters
}
Repository
@Repository
public interface UserRepository
extends PagingAndSortingRepository<User, String>, JpaSpecificationExecutor<User> {
}
Updates regarding how the user is being fetched
The user is fetched by his ID from the request, we'll run a native query by joining two other tables by fetching only the required fields. So in the process of fetch, we are not using the isMigrated
column, plus that attribute (call hierarchy) is set only when a user is created and this is a different API.
Once we fetch the user, it's reference is set to an attribute of another bean RequestInfo
with a Request scope (@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
), which will be used all along the API. Now in the service layer we use the RequestInfo
to get the user, then we set the new status and call the save
method.
@Query(value = "select um.USER_ID,FIRST_NAME,LAST_NAME,USER_STATUS,um.MOB,EMAIL_ID,ENTITY_TYPE,PROFILE_ID,PARENT_ID,SOFT_DELETE, NATIONALITY_ID,DOB,GENDER,FATHER_NAME,QUALIFICATION,LANGUAGE_ID,DESIGNATION,CONTRACT_START_DATE, "
+ "CONTRACT_END_DATE, REGISTERED_DATE,ACTIVATED_DATE,CREATED_BY,CONTACT_EMAIL_ID,CONTACT_MSISDN,ERP_CODE, "
+ "LAST_FINANCIAL_TXN_DATE,MM_APP_VERSION,MM_APP_LAST_UPDATE_DATE,OFFICIAL_EMAIL_ID,SRC_OF_FUND,POW, JOB_NAME,JOB_STARTED,MONTHLY_INCOME, "
+ "MARITAL_STATUS,SALUTE,HIER_ID,LABEL_ID,PROFILE_PICTURE_ID,DOC_NAME,lm.ID , lm.ALERT_DATE , lm.BLOCKED_DATE , lm.IS_FORCE_PIN , lm.IS_FORCE_PASSWORD , lm.LAST_LOGIN_TIME , lm.LAST_NOTIFIED_DATE ,lm.PASSWORD , lm.PIN , "
+ "lm.WRONG_PIN_ATTEMPT , lm.PIN_EXPIRY_DATE , lm.WRONG_PWD_ATTEMPT , lm.PWD_EXPIRY_DATE , lm.USER_NAME, am.ID aid, am.ADDRESS_1, am.ADDRESS_2, am.ADDRESS_TYPE, am.CITY , am.PIN_CODE , am.POST_BOX , am.STATE , am.STREET_NAME,ui.ID_TYPE, ui.ID_NO,um.NOTIFICATION_SERVICE_TYPE "
+ " FROM USER_TABLE um inner join USER_LOGIN_TABLE lm ON um.USER_ID=lm.USER_ID and um.USER_ID=?1 "
+ " left outer join USER_ADDRESS_TABLE am ON um.USER_ID=am.USER_ID left outer join USER_IDENTI_CATION_DETAILS ui ON um.USER_ID = ui.USER_ID", nativeQuery = true)
List<Object[]> getUserByUserId(String userId);
Updates regarding the columns that are not fetched while getting a user - Asked by Ratul Sharker
There are a few columns that we are not fetching, like deviceId
, deviceIp
, etc. These are String
types, so even though we are not providing a default value to these fields null
will be assigned as the default value. So my doubt is why the default value is inserted into isMigrated
and why the same is not inserted to the other two fields because these three are not fetched in the above query right?