We are using Spring JPA with MySQL. While inserting values into the table, the string values are inserted with double quotes. Kindly let me know how to resolve this issue.
We are using MySQL 8, spring-boot-starter-data-jpa-2.0.1.RELEASE.jar and Java 11.
#Override
public Response createNamespace(Namespace namespaceDto) throws AdminException {
try {
com.###.tcp.ens.adminservice.entity.Namespace namespace =
new com.###.tcp.ens.adminservice.entity.Namespace();
namespace.setNamespace(namespaceDto.getNameSpace());
namespace.setAssociatedAppTrn(namespaceDto.getAssociatedAppTrn());
namespace.setAdmins(namespaceDto.getAdminUser());
if (namespaceRepository.findByNamespace(namespaceDto.getNameSpace()).isPresent()) {
return AdminHelper.exceptionHandler(new Exception(),
HttpStatus.UNPROCESSABLE_ENTITY,
AdminStatus.NAMESPACE_EXISTS,
AdminStatus.NAMESPACE_EXISTS.message());
} else {
namespaceRepository.save(namespace);
return Response.status(HttpStatus.CREATED.value()).entity(namespace).build();
}
} catch (DataAccessResourceFailureException exception) {
return AdminHelper.exceptionHandler(exception, HttpStatus.INTERNAL_SERVER_ERROR,
AdminStatus.NAMESPACE_CREATE_FAILED,
AdminStatus.NAMESPACE_CREATE_FAILED.message());
}
}
Expected output is :
'58', 'com.test.tcp3', 'some text5,some text6'
Actual output is :
'57', '\"com.test.tcp3\"', '\"some text5,some text6\"'
Related
Need guideline -
How to do hard delete when no reference is available and do soft delete when reference is available, this operation should be performed in a single method itself.
E.g.
I have 1 master table and 3 transactional tables and the master reference is available in all 3 transactional tables.
Now while deleting master row - I have to do the following: If master reference is available then update the master table row and if no master ref. is available delete the row.
I tried following so far.
Service Implementation -
public response doHardOrSoftDelete(Employee emp) {
boolean flag = iMasterDao.isDataExist(emp);
if(flag) {
boolean result = iMasterDao.doSoftDelete(emp);
} else {
boolean result = iMasterDao.doHardDelete(emp);
}
}
Second Approach:
As we know that while deleting a record if the reference is available then it throws ConstraintViolationException so simply we can catch it and check that caught exception is of type ConstraintViolationException or not, if yes then call doSoftDelete() method and return the response. So here you don't need to write method or anything to check the references. But I'm not sure whether it is the right approach or not. Just help me with it.
Here is what I tried again -
public Response deleteEmployee(Employee emp) {
Response response = null;
try{
String status= iMasterDao.deleteEmployeeDetails(emp);
if(status.equals("SUCCESS")) {
response = new Response();
response.setStatus("Success");
response.setStatusCode("200");
response.setResult("True");
response.setReason("Record deleted successfully");
return response;
}else {
response = new Response();
response.setStatus("Fail");
response.setStatusCode("200");
response.setResult("False");
}
}catch(Exception e){
response = new Response();
Throwable t =e.getCause();
while ((t != null) && !(t instanceof ConstraintViolationException)) {
t = t.getCause();
}
if(t instanceof ConstraintViolationException){
boolean flag = iMasterDao.setEmployeeIsDeactive(emp);
if(flag) {
response.setStatus("Success");
response.setStatusCode("200");
response.setResult("True");
response.setReason("Record deleted successfully");
}else{
response.setStatus("Fail");
response.setStatusCode("200");
response.setResult("False");
}
}else {
response.setStatus("Fail");
response.setStatusCode("500");
response.setResult("False");
response.setReason("# EXCEPTION : " + e.getMessage());
}
}
return response;
}
Dao Implementation -
public boolean isDataExist(Employee emp) {
boolean flag = false;
List<Object[]> tbl1 = session.createQuery("FROM Table1 where emp_id=:id")
.setParameter("id",emp.getId())
.getResultList();
if(!tbl1.isEmpty() && tbl1.size() > 0) {
flag = true;
}
List<Object[]> tbl2 = session.createQuery("FROM Table2 where emp_id=:id")
.setParameter("id",emp.getId())
.getResultList();
if(!tbl2.isEmpty() && tbl2.size() > 0) {
flag = true;
}
List<Object[]> tbl3 = session.createQuery("FROM Table3 where emp_id=:id")
.setParameter("id",emp.getId())
.getResultList();
if(!tbl3.isEmpty() && tbl3.size() > 0) {
flag = true;
}
return flag;
}
public boolean doSoftDelete(Employee emp) {
empDet = session.get(Employee.class, emp.getId());
empDet .setIsActive("N");
session.update(empDet);
}
public boolean doHardDelete(Employee emp) {
empDet = session.get(Employee.class, emp.getId());
session.delete(empDet);
}
No matter how many transactional tables will be added with master tbl reference, my code should do the operations(soft/hard delete) accordingly.
In my case, every time new transactional tables get added with a master reference I've do the checks, so Simply I want to skip the isDataExist() method and do the deletions accordingly, how can I do it in a better way?
Please help me with the right approach to do the same.
There's a lot of repeated code in the body of isDataExist() method which is both hard to maintain and hard to extend (if you have to add 3 more tables the code will double in size).
On top of that the logic is not optimal as it will go over all tables even if the result from the first one is enough to return true.
Here is a simplified version (please note that I haven't tested the code and there could be errors, but it should be enough to explain the concept):
public boolean isDataExist(Employee emp) {
List<String> tableNames = List.of("Table1", "Table2", "Table3");
for (String tableName : tableNames) {
if (existsInTable(tableName, emp.getId())) {
return true;
}
}
return false;
}
private boolean existsInTable(String tableName, Long employeeId) {
String query = String.format("SELECT count(*) FROM %s WHERE emp_id=:id", tableName);
long count = (long)session
.createQuery(query)
.setParameter("id", employeeId)
.getSingleResult();
return count > 0;
}
isDataExist() contains a list of all table names and iterates over these until the first successful encounter of the required Employee id in which case it returns true. If not found in any table the method returns false.
private boolean existsInTable(String tableName, Long employeeId) is a helper method that does the actual search for employeeId in the specified tableName.
I changed the query to just return the count (0 or more) instead of a the actual entity objects as these are not required and there's no point to fetch them.
EDIT in response to the "Second approach"
Is the Second Approach meeting the requirements?
If so, then it is a "right approach" to the problem. :)
I would refactor the deleteEmployeeDetails method to either return a boolean (if just two possible outcomes are expected) or to return a custom Enum as using a String here doesn't seem appropriate.
There is repeated code in deleteEmployeeDetails and this is never a good thing. You should separate the logic which decides the type of the response from the code that builds it, thus making your code easier to follow, debug and extend when required.
Let me know if you need a code example of the ideas above.
EDIT #2
Here is the sample code as requested.
First we define a Status enum which should be used as return type from MasterDao's methods:
public enum Status {
DELETE_SUCCESS("Success", "200", "True", "Record deleted successfully"),
DELETE_FAIL("Fail", "200", "False", ""),
DEACTIVATE_SUCCESS("Success", "200", "True", "Record deactivated successfully"),
DEACTIVATE_FAIL("Fail", "200", "False", ""),
ERROR("Fail", "500", "False", "");
private String status;
private String statusCode;
private String result;
private String reason;
Status(String status, String statusCode, String result, String reason) {
this.status = status;
this.statusCode = statusCode;
this.result = result;
this.reason = reason;
}
// Getters
}
MasterDao methods changed to return Status instead of String or boolean:
public Status deleteEmployeeDetails(Employee employee) {
return Status.DELETE_SUCCESS; // or Status.DELETE_FAIL
}
public Status deactivateEmployee(Employee employee) {
return Status.DEACTIVATE_SUCCESS; // or Status.DEACTIVATE_FAIL
}
Here is the new deleteEmployee() method:
public Response deleteEmployee(Employee employee) {
Status status;
String reason = null;
try {
status = masterDao.deleteEmployeeDetails(employee);
} catch (Exception e) {
if (isConstraintViolationException(e)) {
status = masterDao.deactivateEmployee(employee);
} else {
status = Status.ERROR;
reason = "# EXCEPTION : " + e.getMessage();
}
}
return buildResponse(status, reason);
}
It uses two simple utility methods (you can make these static or export to utility class as they do not depend on the internal state).
First checks if the root cause of the thrown exception is ConstraintViolationException:
private boolean isConstraintViolationException(Throwable throwable) {
Throwable root = throwable;
while (root != null && !(root instanceof ConstraintViolationException)) {
root = root.getCause();
}
return root != null;
}
And the second one builds the Response out of the Status and a reason:
private Response buildResponse(Status status, String reason) {
Response response = new Response();
response.setStatus(status.getStatus());
response.setStatusCode(status.getStatusCode());
response.setResult(status.getResult());
if (reason != null) {
response.setReason(reason);
} else {
response.setReason(status.getReason());
}
return response;
}
If you do not like to have the Status enum loaded with default Response messages, you could strip it from the extra info:
public enum Status {
DELETE_SUCCESS, DELETE_FAIL, DEACTIVATE_SUCCESS, DEACTIVATE_FAIL, ERROR;
}
And use switch or if-else statements in buildResponse(Status status, String reason) method to build the response based on the Status type.
I'm using the Parse API to query some data for an Android application and I would like to know how to return a value (for example a Boolean) from a Parse Query. For example I would like a function that returns true if some data exists and false otherwise like so :
public Boolean myFunction(){
ParseQuery<ParseObject> query = ParseQuery.getQuery();
query.findInBackground("someData",new GetCallback<ParseObject>() {
#Override
public void done(ParseObject lan, ParseException e) {
if(e==null){
return true;
} else {
return false;
}
});
}
I do know that this cannot be done this way because the query is processed in a background thread and I'm not very familiar with Callbacks.
I am aware that there is a similar question here Parse.com how to get return value of query but this is for JavaScript.
Do you have any idea on how to do that ?
You are almost there. When you get the Parse Object extract it with:
boolean myBoolean = myParseObject.getBoolean("myBooleanColumn");
Full example (finding an object via id, it can be adapted for other type of queries):
ParseQuery<ParseObject> query = ParseQuery.getQuery("YourClass");
query.getInBackground("id", new GetCallback<ParseObject>() {
public void done(ParseObject myParseObject, ParseException e) {
if (e == null) {
boolean myBoolean = myParseObject.getBoolean("myBooleanColumn");
} else {
// something went wrong
}
}
});
Update: if you only want to check if some data exists in a row you can do it with
query.whereEqualTo("columnToFind", "searchterm");
You can even find compare an array with the data in row with
query.whereContainsAll("columnToFind", arrayOfThingsToSearch);
After some research and thanks to #buckettt, the easiest way to accomplish that is to use Parse Cloud Code. Define your function in the main.js file inside parse-server folder :
Parse.Cloud.define("myFunction",function(req,res){
var userId = req.params.userId; //params passed in Client code
var myQuery = new Parse.Query(Parse.User);
myQuery.equalTo("userId", userId);
myQuery.find({
success: function(results) {
res.success(results.get("userName"));
}
error: function() {
res.error("Failed !");
}
}
});
And in your Client's code :
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("userId",userId);
ParseCloud.callFunctionInBackground("myFunction", params, new FunctionCallback<String>() {
public void done(String res,ParseException e){
if (e == null) {
Log.i("Results :",res);
} else {
Log.i("Error",e.getMessage());
}
}
});
This way you return the desired value and the function is executed directly on your server. Hope this helps
I am trying to query an entire column data for eg:
SELECT USER_USERNAME FROM xxxx WHERE USER_USERNAME=?
I'm getting error
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
My Dao
#Override
public String getAllUsers(UserRegistration uname) {
System.out.println(uname.getUserName());
return template.queryForObject(GET_USER_USERNAME, new Object[] { uname.getUserName() },
new BeanPropertyRowMapper<String>(String.class));
}
I'm injecting the properties through xml file.
my controller
#RequestMapping(method = RequestMethod.POST,value = "/checkUserName", headers = "Accept=application/json")
public org.weber.nag.model.UserRegistration checkUserName(#RequestBody org.weber.nag.model.UserRegistration userReg) {
userDao.getAllUsers(userReg);
return userReg;
}
So from the above when i am trying to pass the username from postman it takes the values to controller and from there I'm passing it to my dao to compare whether the name exits or not.The name successfully reaches my dao but I get an error.
So I tried to catch the exception
#Override
public String getAllUsers(UserRegistration uname) {
System.out.println(uname.getUserName());
try {
return template.queryForObject(GET_USER_USERNAME, new Object[] { uname.getUserName() },
new BeanPropertyRowMapper<String>(String.class));
} catch (EmptyResultDataAccessException e) {
System.out.println("uname already exists");
return "user exists";
}
}
But every time it prints
"uname already exists"
irrespective of the username given whether it is there in db or not.
In JdbcTemplate , queryForInt, queryForLong, queryForObject all such methods expects that executed query will return one and only one row.
If you get no rows that will result in EmptyResultDataAccessException.
From the javadoc of EmptyResultDataAccessException
Data access exception thrown when a result was expected to have at
least one row (or element) but zero rows (or elements) were actually
returned.
Make sure the query you are using should return only one row.
If at all it is not possible then use query method instead of queryForObject.
Tip: To debug this, run the same query in an SQL IDE directly.
#Override
public String getAllUsers(UserRegistration uname) {
try {
template.queryForObject(GET_USER_USERNAME, new Object[] { uname.getUserName() },
new BeanPropertyRowMapper<String>(String.class));
System.out.println("uname exists");
return "user name is NOT available.";
} catch (EmptyResultDataAccessException e) {
System.out.println("uname do not exists");
}
return "user is available";
}
I'm trying to delete objects from the datastore (using cloud endpoints)
I know the connection is valid because I'm pulling/inserting objects with no problem
However when I try to delete using various approaches I get the same exception
java.lang.illegalArgumentException:DELETE with non-zero content length is not supported
approach 1(using the raw datastore service and the key I stored when inserting the item):
#ApiMethod(name = "removeRPurchase")
public RPurchase removeRPurchase(RPurchase purchase) {
NamespaceManager.set(purchase.getAccount());
DatastoreService d=DatastoreServiceFactory.getDatastoreService();
Key k=KeyFactory.stringToKey(purchase.getKeyrep());
try {
d.delete(k);
} catch (Exception e) {
e.printStackTrace();
purchase=null;
}
return purchase;
}
Approach 2
#ApiMethod(name = "removeRPurchase")
public RPurchase removeRPurchase(RPurchase purchase) {
NamespaceManager.set(purchase.getAccount());
Key k=KeyFactory.stringToKey(purchase.getKeyrep());
EntityManager mgr = getEntityManager();
RPurchase removed=null;
try {
RPurchase rpurchase = mgr.find(RPurchase.class, k);
mgr.remove(rpurchase);
removed=rpurchase;
} finally {
mgr.close();
}
return removed;
}
Ive also tried various variations with the entity manager and the Id, but all with the same exception
The object that i've passed in does contain the namespace in the account, and it does contain the 'KeytoString' of the key associated with the object
the endpoint is called as it should in an AsyncTask endpoint.removeRPurchase(p).execute();
Any help suggestions are appreciated
Make your API method a POST method like this:
#ApiMethod(name = "removeRPurchase" path = "remove_r_purchase", httpMethod = ApiMethod.HttpMethod.POST)
public RPurchase removeRPurchase(RPurchase purchase) {
NamespaceManager.set(purchase.getAccount());
DatastoreService d=DatastoreServiceFactory.getDatastoreService();
Key k=KeyFactory.stringToKey(purchase.getKeyrep());
try {
d.delete(k);
} catch (Exception e) {
e.printStackTrace();
purchase=null;
}
return purchase;
}
I had the same problem because I was using httpMethod = ApiMethod.HttpMethod.DELETE. The error it gives is correct. Simply change it to a POST and do whatever you want inside that API method like delete entities, return entities, etc.
How about trying out the following :
#ApiMethod(
name = "removeRPurchase",
httpMethod = HttpMethod.DELETE
)
public void removeRPurchase(#Named("id") String id) {
//Now take the id and plugin in your datastore code to retrieve / delete
}
had several apps with jdbc and Oracle 10g. Now I´m changing the apps for use c3p0. But I have some problems working with Oracle types.
I Have this Oracle type:
CREATE OR REPLACE
TYPE DATAOBJ AS OBJECT
(
ID NUMBER,
NAME VARCHAR2(50)
)
And this Oracle function:
CREATE OR REPLACE FUNCTION F_IS_DATA_OBJECT (datar in DATAOBJ) RETURN varchar2 IS
tmpVar varchar2(150);
BEGIN
tmpVar := 'Data object:';
if datar.id is not null then
tmpVar := tmpVar || 'id=' || datar.ID;
end if;
if datar.name is not null then
tmpVar := tmpVar || 'name=' || datar.name;
end if;
return tmpVar;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
RAISE;
END F_IS_DATA_OBJECT;
then I have a app in Java with c3p0 with next classes:
Dataobj.class to represent the object type:
package c3p0pruebas.modelo;
import java.io.Serializable;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
public class Dataobj implements SQLData, Serializable {
private String name;
private Integer id;
public Dataobj() {
}
public String getSQLTypeName() {
return "DATAOBJ";
}
public void writeSQL(SQLOutput stream) throws SQLException {
stream.writeInt(id.intValue());
stream.writeString(name);
}
public void readSQL(SQLInput stream, String typeName) throws SQLException {
id = new Integer(stream.readInt());
name = stream.readString();
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
... and its gets and sets ....
And the main class and main method:
Connection connection = DBConnectionManager.getInstance().getConnection("Mypool"); //I use a class to get connection
CallableStatement cs = null;
String error = "";
try {
/*
//First I made a NativeExtractor of the connection, but the result is the same, I got it from Spring framework.
//C3P0NativeJdbcExtractor extractor = new C3P0NativeJdbcExtractor();
//OracleConnection newConnection = (OracleConnection) extractor.getNativeConnection(connection);
//cs = (OracleCallableStatement) newConnection.prepareCall("{? = call F_IS_DATA_OBJECT(?)}");
*/
//Creates the object
Dataobj obj = new Dataobj();
obj.setId(new Integer(33));
obj.setName("myName");
cs = connection.prepareCall("{? = call F_IS_DATA_OBJECT(?)}");
cs.registerOutParameter(1, OracleTypes.VARCHAR);
cs.setObject(2, obj);
cs.execute();
error = cs.getString(1);
System.out.println("Result: " + error);
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
closeDBObjects(null,cs,null);
}
closeDBObjects(null, null, connection); //Close connection
The execution gets:
Data object: id=33.
I cant get the String (Varchar2) value, the name string.
With oracle arrays of object type, I have the same problem, It worked nice with JDBC. When I worked with Arrays, also, it hasn´t the string values:
//Here I use a NativeConnection ...
Dataobj arrayOfData[] = new Dataobj[myDataObj.size()];
... //Makes the array of DataObj.
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("OBJ_ARRAY", newConnection);
ARRAY arrayDatas = new ARRAY(descriptor, newConnection, arrayOfData);
//In this step, objects of arrayDatas haven´t the name string...
Thanks!!!
OK, It finally works.
Searching, We found out the answer:
We change data definition in the database and now it works:
CREATE OR REPLACE
TYPE "DATAOBJ" AS OBJECT
(
vid NUMBER,
vname NCHAR(50)
)
Thanks!
I had the same problem and i solved without change VARCHAR2 to NCHAR, because for me, the NCHAR doesn't appear the String in the Oracle, stay "?" in all the positions.
I changed the oracle driver of the WAR to the version of my database, in my case was 11.2.0.1.0:
http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html
And i put another driver, that is the NLS for Oracle Objects and Collections:
http://download.oracle.com/otn/utilities_drivers/jdbc/112/orai18n.jar
With this, i solved the problem and the VARCHAR2 worked fine.
Good luck.