I have created a simple java application as my college mini project in which one of the module I'm allowing users to perform operations like insert, delete, update and search.
For validation purposes I want a to display an error message to the user if he tries to delete a record which isn't present in the DB like
"Sorry record not found" .
I have tried try catch block to check that if mongodb throws a exception if document not found but that didn't worked. I'm new in Java and Mongodb and need help.
Here's my code of deleteActionPerformed and of what I tried:
private void deleteActionPerformed(java.awt.event.ActionEvent evt) {
try {
// my collection name is activity
DBCollection col = db.getCollection("activity");
// Tid is the TextField in which i am taking input of _id
if(!Tid.getText().equals("")) {
col.remove(new BasicDBObject().append("_id",(Object)Tid.getText()));
} else {
JOptionPane.showMessageDialog(null,"Please Enter the ID");
}
} catch(Exception e){
JOptionPane.showMessageDialog(null,"Record not Found " + e);
}
}
The try catch block is not generating a not found type exception.
This may not by the most efficient method, but it ought to work.
I adapted it from some code of mine looking for a particular document value (other than _id).
There may be a specialized method for _id.
/**
* Checks if an activity exists with a given id. if no such activity exists
* returns false. Returns true for one or more activities with a matching id.
*
* #param db
* #param id
* #return boolean - true if one or more functions with matching names exit.
*/
public static boolean activityExists(MongoDatabase db, ObjectId id) {
FindIterable<Document> iterable = db.getCollection("activity")
.find(new Document("_id", id));
return iterable.first() != null;
}
EDIT: It seems that it is best to use the count method. Please refer to the following answer:
How to check if document exists in collection using mongo Java driver 3.0+
In your case, it is significantly faster to use find() + limit() because findOne() will always read + return the document if it exists. find() just returns a cursor (or not) and only reads the data if you iterate through the cursor.
So instead of:
db.collection.findOne({_id: “myId”}, {_id: 1})
you should use:
db.collection.find({_id: “myId”}, {_id: 1}).limit(1)
Related
I am really struggling here and have looked at other questions but just cant seem to get the answer I need.
What I am trying to do is pull through all the unique values of a column and then iterate through them and add them to an array. Ending up with the one column being stored in my array, but one of each value that exists not the multiple like there currently is.
Every time I try and do .distinct it asks me for the return class I have tried many different class but it just doesn't seem to work... Code is below any help would be appreciated.
public static void MediaInteraction() {
//Storing data from MediaInteraction in MediaArray
//BasicDBObject Query = new BasicDBObject();
//Query.put("consumerid", "");
MongoCursor<Document> cursormedia = collectionmedia.distinct("consumerid", (What do I put here?)).iterator();
while (cursormedia.hasNext()) {
System.out.println(cursormedia.next());
MediasessionID.add(cursormedia.next());
}
System.out.println("Media Array Complete");
System.out.println(MediasessionID.size());
}
The change that you probably want to introduce shall be somewhat like -
MongoCursor<Document> cursormedia = collectionmedia.distinct("consumerid",
<ConsumerId-DataType>.class).iterator(); //please replace the consumerId field's datatype here
Also from the docs -
/**
* Gets the distinct values of the specified field name.
*
* #param fieldName the field name
* #param resultClass the class to cast any distinct items into.
* #param <TResult> the target type of the iterable.
* #return an iterable of distinct values
* #mongodb.driver.manual reference/command/distinct/ Distinct
*/
<TResult> DistinctIterable<TResult> distinct(String fieldName, Class<TResult> resultClass);
So in your example, if you are trying to attain cursor for Document you probably want to use Document.class in the above suggested code.
Edit - Also the fact that you are calling cursormedia.next() twice the count of your MediasessionID would be halved. Suggest you do that(.next) once improving it further to obtain results.
I have created web service in JAVA Netbeans and called MySQL data through rest web service.
Edited code:
For loop shows all areas in sorting order then why as json output all data are not displayed in ascending order???
my method is as follows :
#GET
#Path("/ShowAreasDup")
#Produces(MediaType.APPLICATION_JSON)
public List<EntityAreas> ShowAreasDup(){
ArrayList<EntityAreas> listSort;
try{
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection(DB_URL,USER,PASSWORD);
String query = "SELECT * FROM Areas ORDER BY AreaName";
Statement statement = conn.createStatement();
ResultSet resultset = statement.executeQuery(query);
// iterate through the java resultset
while (resultset.next())
{
int id = resultset.getInt("AreaID");
String restroName = resultset.getString("AreaName");
EntityAreas anames=new EntityAreas();
anames.setAreaid(id);
anames.setAreaname(restroName);
ShowentityAreas.put(id, anames);
}
statement.close();
}
catch(HeadlessException | SQLException |ClassNotFoundException ee)
{
JOptionPane.showMessageDialog(null, ee);
}
listSort=new ArrayList<EntityAreas>(ShowentityAreas.values());
Collections.sort(listSort,new Comparator<EntityAreas>(){
#Override
public int compare(EntityAreas o1, EntityAreas o2) {
return o1.getAreaname().compareTo(o2.getAreaname());
}
});
for(EntityAreas entityarea:listSort){
System.out.println(entityarea);
}
return listSort;
}
thank you in advance for help
Edit :
Above code is works perfectly for me
thanks to all for giving me a direction to the answser :)
Given your code, there could be some hypothesis. The most probable is that ShowAreas stores the information in an non ordered data structure (for example an HashMap).
If you want to maintain your values in order , you have to use some additional data structure. For example, you can use a TreeSet for the values.
Another solution could be to sort the values immediatly before returning them (javadoc),
// Get the elements
List<Areas> areas = new ArrayList<Areas>(ShowAreas.values());
// Sort them
Collections.sort(areas);
// Return them
return areas;
Pay attention: if you want to use this method, the class Areas must implement Comparable.
A last advise: don't put the code that interacts with the database in the class that has the responsibility to receive external REST calls. You violates the single responsibility principle and your application will become unmaintainable very quickly. Try to use a structure Controller - Service - Repository.
I am trying to add a filter to check for duplicate values that a user might input. I am not sure where I am going going wrong in my query.
My query doesnot enter the loop to check if the name already exists.
I am fairly new to google-could. If someone can tell me on how I can fix my problem or if there is a better solution.
else if ( commandEls[0].equals( "add_director" ) ) {
String name = commandEls[1];
String gender = commandEls[2];
String date_of_birth = commandEls[3];
boolean duplicate = false;
//add a director record with the given fields to the datastore, don't forget to check for duplicates
Entity addDirectorEntity = new Entity("Director");
// check if the entity already exits
// if !duplicate add, else "Already exisits"
Query directorExists = new Query("Movies");
// Director Name is the primary key
directorExists.addFilter("directorName",Query.FilterOperator.EQUAL, name);
System.out.print(name);
PreparedQuery preparedDirectorQuery = datastore.prepare(directorExists);
System.out.print("outside");
for(Entity directorResult : preparedDirectorQuery.asIterable()){
// result already exists in the database
String dName = (String) directorResult.getProperty(name);
System.out.print(dName);
System.out.print("finish");
duplicate = true;
}
if(!duplicate){
addDirectorEntity.setProperty("directorName",name);
addDirectorEntity.setProperty("directorGender",gender);
addDirectorEntity.setProperty("directorDOB",date_of_birth);
try{
datastore.put(addDirectorEntity);
results = "Command executed successfully!";
}
catch(Exception e){
results = "Error";
}
}
else {
results = "Director already exists!";
}
}
Non-ancestor queries (like the one in your example) are eventually consistent, so they cannot reliably detect duplicate property values. Ancestor queries are fully consistent, but they require structuring your data using entity groups, and that comes at the cost of write throughput.
If the directorName property in your example is truly unique, you could use it as the name in the key of your Director entities. Then, when you are inserting a new Director entity, you can first check if it already exists (inside of a transaction).
There's no general, built-in way in Datastore to ensure the uniqueness of a property value. This related feature request contains discussion of some possible strategies for approximating a uniqueness constraint.
I'd also recommend reading up on queries and consistency in the Datastore.
That is a valid thing to do but i figured out my problem.
I am making an Entity for Director where as That should be for movies.
How do I enable ResultSet.getRow() in CsvJdbc?
(this is a function that is supposed to return the current row number)
It appears to be dependent on an isScrollable member. If anyone has encountered this before, how do you work around it?
Is it a property I need to set in the Properties object passed in?
Would I need to "sanitize" or somehow modify my CSV files in any way?
Thanks!
More Info
An application I use has the capability of importing data from any JDBC source. I need to get some data from CSV files into it, hence I'm using CsvJdbc. This application needs to access the row numbers of each line of data it imports, and unfortunately CsvResultSet#getRow() throws an exception, complaining that "Csv Jdbc : ResultSet.getRow() unsupported".
The following is the impl. of the getRow() method in CsvJdbc (1.0.5)
/**
* Retrieves the current row number. The first row is number 1, the
* second number 2, and so on.
*
* #return the current row number; <code>0</code> if there is no current row
* #exception SQLException if a database access error occurs
*/
public int getRow() throws SQLException {
if (this.isScrollable == ResultSet.TYPE_SCROLL_SENSITIVE) {
return currentRow;
} else {
throw new UnsupportedOperationException(
"ResultSet.getRow() unsupported");
}
}
Looking through the rest of the source it seems that the only place that the isScrollable member property is set is in the constructor and as a default value.
Have you tried creating a scrollable statement...
Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
I have some records to import. It's ok the first time when they are being inserted. If I try to import the same data again I receive a org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint. How can I update the records in the database if the data is the same/or changed and insert if it's new data using JDBC?
public void store(Object entity) throws Exception {
try {
if (this.updateEntity((XEntity) entity) == 0) {
this.insertEntity((XEntity) entity);
}
...
} catch (SQLException sqlEx) {
...
}
}
private int updateEntity(XEntity entity) throws SQLException {
PreparedStatement prepStmt = this.getUpdatePreparedStmt();
...
return prepStmt.executeUpdate();
}
private void insertEntity(XEntity entity) throws SQLException {
...
this.getInsertPreparedStmt().executeUpdate();
}
The problem is fixed now. I've provided an answer below.
You can try using postgres SQL 'MERGE' or 'REPLACE'
You can pass the UPDATE command as a string through JDBC.
According to this SO post, you will have to write 2 statements.
If you want to use the same method to insert and update your data, you'll need to check if the data exists first. The SQL command used to insert a new object is INSERT, whereas the one used to update an element is UPDATE. So, what you could do is do a SELECT to check if your data is already here, and then do an INSERT or UPDATE based on the results.
However, this is a workaround. You would really need to clarify your implementation, and make different methods whether you are adding or updating data. Business-side, these are clearly two very different functions, so one method for both seems to me like a design problem.
This test logic works.
if (this.updateEntity((XEntity) entity) == 0) {
this.insertEntity((XEntity) entity);
}
The problem was in the method that updated the record. The WHERE clause in the update prepared statement was using different data(data containing spaces) so updateEntity would always return 0. That was the reason why only inserts were made, instead of updates. Thank you very much for your help.