Hibernate Restrictions.in() only accepts propertyName as String - java

I have a List of ids:
List<Object> ids;
I need to use this in a criteria query to get all rows with an id that ids contains.
What I have now and works:
if (ids.size() > 0) {
for (Object id : ids) {
preparedResults.add((T)sessionMngr.getSession().
createCriteria(rowType).add(Restrictions.idEq(id))
.uniqueResult());
}
}
So I fetch them one by one, which isn't optimal, but I first tried something like following to get them in one query, but don't know what to put at the ???:
preparedResults.addAll(sessionMngr.getSession().
createCriteria(rowType).
add(Restrictions.in(???, ids)).list());
The first argument of Restrictions.in() is of type String. I can't put a hard coded "id" there as I don't know what the propertyname is.
So I don't know how to get the id property as a String there.
I saw Projections.id(), but I am not sure if I can use this to get it as a String.

With this solution you can retrieve the name of the id field of your entity. If you use annotations you can have it even shorter as described here. If you donĀ“t use composite primary keys you could also use
ClassMetadata classMetadata = getSessionFactory().getClassMetadata(myClass);
string identifierPropertyName = classMetadata.getIdentifierPropertyName();
Source of this snippet: here

Related

Mongo Java - prefexing a field value with some constant in all the docs

I have so many documents in a collection and would like to change one of the filed name in all the documents. Also, want to change the value with some prefixed constant in all the docs.
Example,
{
"_id" : ObjectId("56e9e6e9083378ba4e5e8832"),
"name" : "Mike"
}
Should be changed to,
{
"_id" : ObjectId("56e9e6e9083378ba4e5e8832"),
"firstName" : "First-Mike"
}
I used the following Java code to rename the field,
final MongoDatabase mongoDb = mongo.getDatabase(database);
final MongoCollection<Document> collection = mongoDb.getCollection("<CollectionName>");
Bson rename = Updates.rename("name", "firstName");
collection.updateMany(new Document(), rename);
But not sure, how to change the value with some prefixed constants for all the documents in the collection.
I can iterate all the documents in the collection and do the change, but trying to understand, if there is any way we can do this without iterating all the documents, like single update.
Thanks
Why not use regular expressions for prefix matching? A single update command can do your job if you use mongodb's regex:
https://docs.mongodb.org/manual/reference/operator/query/regex/

Mongodb avoid duplicate entries

I am newbie to mongodb. May I know how to avoid duplicate entries. In relational tables, we use primary key to avoid it. May I know how to specify it in Mongodb using java?
Use an index with the {unique:true} option.
// everyone's username must be unique:
db.users.createIndex({email:1},{unique:true});
You can also do this across multiple fields. See this section in the docs for more details and examples.
A unique index ensures that the indexed fields do not store duplicate values; i.e. enforces uniqueness for the indexed fields. By default, MongoDB creates a unique index on the _id field during the creation of a collection.
If you wish for null values to be ignored from the unique key, then you have to also make the index sparse (see here), by also adding the sparse option:
// everyone's username must be unique,
//but there can be multiple users with no email field or a null email:
db.users.createIndex({email:1},{unique:true, sparse:true});
If you want to create the index using the MongoDB Java Driver. Try:
Document keys = new Document("email", 1);
collection.createIndex(keys, new IndexOptions().unique(true));
This can be done using "_id" field although this use is discouraged.
suppose you want the names to be unique, then you can put the names in "_id" column and as you might know "_id" column is unique for each entry.
BasicDBObject bdbo = new BasicDBObject("_id","amit");
Now , no other entry can have name as "amit" in the collection.This can be one of the way you are asking for.
As of Mongo's v3.0 Java driver, the code to create the index looks like:
public void createUniqueIndex() {
Document index = new Document("fieldName", 1);
MongoCollection<Document> collection = client.getDatabase("dbName").getCollection("CollectionName");
collection.createIndex(index, new IndexOptions().unique(true));
}
// And test to verify it works as expected
#Test
public void testIndex() {
MongoCollection<Document> collection = client.getDatabase("dbName").getCollection("CollectionName");
Document newDoc = new Document("fieldName", "duplicateValue");
collection.insertOne(newDoc);
// this will throw a MongoWriteException
try {
collection.insertOne(newDoc);
fail("Should have thrown a mongo write exception due to duplicate key");
} catch (MongoWriteException e) {
assertTrue(e.getMessage().contains("duplicate key"));
}
}
Theon solution didn't work for me, but this one did:
BasicDBObject query = new BasicDBObject(<fieldname>, 1);
collection.ensureIndex(query, <index_name>, true);
I am not a Java programmer however you can probably convert this over.
MongoDB by default does have a primary key known as the _id you can use upsert() or save() on this key to prevent the document from being written twice like so:
var doc = {'name': 'sam'};
db.users.insert(doc); // doc will get an _id assigned to it
db.users.insert(doc); // Will fail since it already exists
This will stop immediately duplicates. As to multithread safe inserts under certain conditions: well, we would need to know more about your condition in that case.
I should add however that the _id index is unqiue by default.
using pymongo it looks like:
mycol.create_index("id", unique=True)
where myCol is the collection in the DB
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["mydatabase"]
mycol = mydb["customers"]
mycol.create_index("id", unique=True)
mydict = {"name": "xoce", "address": "Highway to hell 666", "id": 1}
x = mycol.insert_one(mydict)
Prevent mongoDB to save duplicate email
UserSchema.path('email').validate(async(email)=>{
const emailcount = await mongoose.models.User.countDocuments({email})
return !emailcount
}, 'Email already exits')
May this help ur question...
worked for me..
use in user model.
refer for explaination
THANKS...

Can I get the string from preparedStatem.setString()?

I have a problem - I create my SQL queries dynamically and basing on user input options. So the user has 5 parameters (actually it's more) and he can choose to use some of them (all if he wants) or none and specify their value in the query. So I construct my query String (basic the WHERE conditions) by checking if a parameter was selected and if a value was provided. However now there is the problem of special characters like '. I could try to use replaceAll("'", "\\") but this is quite dull and I know that preparedStatement.setString() does the job better. However for me I would need than to check again if the parameter was provided and if the previous one were also (to specify the poison of ? and connect it to the right parameter). This causes a lot of combinations and does not look elegant.
So my question is - can I somehow receive the string preparedStatement.setString() produces? Or is there a similar function that would do the same job and give me the String so I can put it in the query manually.
Maybe the intro was too long but someone might have a better idea and I wanted to explain why I need it.
What you can do is construct the basic, unparameterized SQL query based on whether the parameters were specified, and then use the prepared statement to fill in the parameters.
It could look something like this (rough sketch):
Map<String, Object> parameterValues = /*from user*/;
List<String> parameterNames = Arrays.asList("field1", "field2", "field3");
List<Object> valueList = new ArrayList<Object>();
StringBuilder statementBuilder = new StringBuilder("select * from table where ");
for ( String parameterName : parameterNames ) {
if ( parameterValues.containsKey(parameterName) ) {
statementBuilder.append(parameterName + " = ? AND");
valueList.add(parameterValues.get(parameterName));
}
}
PreparedStatement st = conn.prepareStatement(statementBuilder.toString(),
valueList);
//set each parameter here.
It's only hard the first time; then you can make it generic. That said there are probably query builders that abstract all of this away for you. I use QueryDSL but that does not have bindings for pure JDBC but rather JPA and JDO, etc.
On another forum I was given a different, simpler and cleaner approach that work perfectly.
Here are some links for others with the same problem:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1669972300346534908
http://www.akadia.com/services/dyn_modify_where_clause.html

MongoDB Composite Key

I'm just getting started with MongoDb and I've noticed that I get a lot of duplicate records for entries that I meant to be unique. I would like to know how to use a composite key for my data and I'm looking for information on how to create them. Lastly, I am using Java to access mongo and morphia as my ORM layer so including those in your answers would be awesome.
Morphia: http://code.google.com/p/morphia/
You can use objects for the _id field as well. The _id field is always unique. That way you kind of get a composite primary key:
{ _id : { a : 1, b: 1} }
Just be careful when creating these ids that the order of keys (a and b in the example) matters, if you swap them around, it is considered a different object.
The other possibility is to leave _id alone and create a unique compound index.
db.things.ensureIndex({firstname: 1, lastname: 1}, {unique: true});
//Deprecated since version 3.0.0, is now an alias for db.things.createIndex()
https://docs.mongodb.org/v3.0/reference/method/db.collection.ensureIndex/
You can create Unique Indexes on the fields of the document that you'd want to test uniqueness on. They can be composite as well (called compound key indexes in MongoDB land), as you can see from the documentation. Morphia does have a #Indexed annotation to support indexing at the field level. In addition with morphia you can define compound keys at the class level with the #Indexed annotation.
I just noticed that the question is marked as "java", so you'd want to do something like:
final BasicDBObject id = new BasicDBObject("a", aVal)
.append("b", bVal)
.append("c", cVal);
results = coll.find(new BasicDBObject("_id", id));
I use Morphia too, but have found (that while it works) it generates lots of errors as it tries to marshall the composite key. I use the above when querying to avoid these errors.
My original code (which also works):
final ProbId key = new ProbId(srcText, srcLang, destLang);
final QueryImpl<Probabilities> query = ds.createQuery(Probabilities.class)
.field("id").equal(key);
Probabilities probs = (Probabilities) query.get();
My ProbId class is annotated as #Entity(noClassnameStored = true) and inside the Probabilities class, the id field is #Id ProbId id;
I will try to explain with an example:
Create a table Music
Add Artist as a primary key
Now since artist may have many songs we have to figure out a sort key.
The combination of both will be a composite key.
Meaning, the Artist + SongTitle will be unique.
something like this:
{
"Artist" : {"s" : "David Bowie"},
"SongTitle" : {"s" : "changes"},
"AlbumTitle" : {"s" : "Hunky"},
"Genre" : {"s" : "Rock"},
}
Artist key above is: Partition Key
SongTitle key above is: sort key
The combination of both is always unique or should be unique. Rest are attributes which may vary per record.
Once you have this data structure in place you can easily append and scan as per your custom queries.
Sample Mongo queries for reference:
db.products.insert(json file path)
db.collection.drop(json file path)
db.users.find(json file path)

grouping data in java

is there someway we can group similar data in java?
i want to group all the data with same id and print it out.
i am querying for the data using jdbc and was searching for a library i could use for this.
any idea?
thanks
Use a Map<GroupID, List<Data>>.
Map<Long, List<Data>> groups = new HashMap<Long, List<Data>>();
while (resultSet.next()) {
Long groupId = resultSet.getLong("groupId");
String col1 = resultSet.getString("col1");
String col2 = resultSet.getString("col2");
// ...
List<Data> group = groups.get(groupId);
if (group == null) {
group = new ArrayList<Data>();
groups.put(groupId, group);
}
group.add(new Data(groupId, col1, col2 /* ... */));
}
You could also just make it a property of another (parent) bean.
See also:
Collections and Maps tutorial
Ideally you should use a where clause in your SQL query to limit the returned data to the id in question:
select *
from table
where id = 'xxxxxx'
Of course if you will be printing out the data for all id's this may be a bad choice, as then your app will perform multiple sql queries, which usually will result in a performance hit.
As for grouping data in Java, take a look at java.util.HashMap (or any of the container classes that implement the Map interface). HashMap is a container of key-value pairs. In your case, the 'key' can be a String (or whichever data type applies) representing your id, and the 'value' can be an object to contain the data associated to the id key (i.e.: ArrayList of Strings, or a new class you define to help you manage the data)
Are you looking for the SQL ORDER BY clause?
SELECT columns
WHERE criteria
ORDER BY id ASC;
That will give you all the data in your criteria and will order it by the id column which naturally means that all the rows with the same id will appear consecutively.

Categories