I am automatically generating user account credentials (login and password). I want generate login by user’s count:
#Override
public Account create(Account account) {
// we will not remove any account from db
long count = accountRepository.count();
account.setLogin("user-" + count);
account.setPassword("randompassword");
return accountRepositry.save(account);
}
But as we know - that’a bad code, cuz is not synchronised.
How I can solve problem with getting actual count() from database? Maybe I can fix that with #Transactional?
Upd: I know that I can fix that with embedded functions in database (like triggers) but can I fix that with Java?
Related
What would be considered an acceptable way of dealing with returning a record from a DB with the following 3 potential outcomes:
Db connection works, finds a user and returns a populated user object
Db connection works, doesn't find a user, returns a new user object
Db connection/query fails...
I'm for the most part aiming for design by contract:
class Scratch {
public User getUser(int id) {
try {
// Prepare SQL Query
PreparedStatement s = this.connection.prepareStatement(
"select * from get_user(?)"
);
// Provide SQL Parameters
s.setInt(1, id);
// Run our SQL
ResultSet rs = s.executeQuery();
rs.next();
// Extract data into Entity
User user = User.createFromDatabase(rs);
rs.close();
return user;
} catch(Exception e) {
e.printStackTrace();
}
return new User();
}
}
In the situation that the DB connection or query fails it's a little less obvious what I should do, I have a few options:
Return a new user object, because our method has agreed to return a user
Pro: This sticks to designing by contracts
Con: This makes it look like the user doesn't exist.
Return null since it didn't actually get a user.
Pro: This is totally clear that a user was not found
Con: Requires a null check
Throw an exception further up the chain.
Pro: Makes it explicitly clear the operation wasn't achieved
Con: Does not attempt to rectify issues where they happen
I'm leaning towards handling Exceptions as it avoids the billion-dollar mistake, and also maintains design by contract in normal situations.
However I'd like to know if there are any obvious pitfalls or if this is a familiar situation with a well established pattern to resolve it.
I would throw an exception and let the user know that the connection failed. Returning NULL is something I would never do because you won't know what the problem was.
I don't know why you would return "New user object" if you don't have connection to the database. You won't be able to save the user.
My choice will be to Throw an exception
Use Optional (please). This make explicit that the user could not be found in the database and avoid NullPointerException's.
Optional(User) if the user is found in the database
Empty if user is not found
If there is an Error you have two options:
Notify the client so it can get feedback and react to this failure. In this case throw an exception and handle it in the proper layer. This should be the default behaviour for most of the applications.
Hide it to the client, this is less common but some times the client doesn't care or you don't want to publish your failures. In that case just return an Empty.
I have a Spring Boot API linked to a mongodb database.
On a specific route I get the events for a user given (it's parsing a big collection with millions documents); the problem is that I get these documents in >20s but when I use mongoshell I get them in 0,5s.
I've already added an index on the userId (it got a way faster).
I've googled the problem but I don't see answers about this (or maybe I didn't get the point).
My method does a very basic thing :
public Collection<Event> getEventsForUser(final String tenantId, final String orgId, final String userId)throws EventNotFoundException {
Collection<MongoEvent> mongoEvents = mongoEventRepository.findByTenantIdAndOrganizationIdAndUserIdIgnoreCase(tenantId, orgId, userId);
if (mongoEvents != null && !mongoEvents.isEmpty())
return mongoEvents.stream().map(MongoEvent::getEvent).collect(Collectors.toList());
throw new EventNotFoundException("Events not found.");
}
Is it normal or is there a solution to optimize the query?
Thanks!
I am new. Trying to do a database retrieve demo to login a system, here is my function code:
I will call goLogin function and pass in the input id and password for validation and I will also get all the id from Database for checking purpose. After ID is correct, only go check the password.
public void goLogin(String id, String pass){
String[99] allID = getAllIDFromDB();
for(int i=0;i<allID.length;i++){
if(allID[i]==id){
String passwordDB = getPasswordFromDB(id);
if(pass==password){
System.out.println("Correct Password");
}else{
System.out.println("Wrong Password");
}
}
}
My peers say I was using too much if else and I can shorten the code and make the program better, and I faced some issue on looping for example when ID and Password are correct, the program will still continue the loop.
Is there any suggestion to make this function better?
First of all, Why retrieve all the user IDs from the database instead make sql query to retrieve the row of this user based on this id.
something like this:
Select * from `users` where id = {id};
And if you want to stop looping a wrong password was found, add break in the else scope.
In my opinion, the main issue of your program is your logic to implement the Login Function.
Login Function implementation can be implemented with various pattern, Based on your program code I will assume you just want a Most Basic Login Function that allow the program to do validation on user input ID and Password.
Actually, this Basic validation can be done in your Database Query. You can just take the user input ID and Password and let Database Query to do filtering and determine if the user input ID and Password is valid or invalid.
First use this Query:
Select DATABASEID From Database Where DATABASEID=inputID and DATABASEPASSWORD=inputPassword;
Java Code:
public void goLogin(String id, String pass){
// Since i changed the Query, you need to pass in the ID and Password to let the Query to filtering
String DatabaseID = getIDFromDB(id, pass);
// Simple Logic, If DatabaseID have value which mean the ID and Password is correct
// Because the Database Query will return null if the ID and Password is Wrong
if(DatabaseID!=null){
System.out.println("ID and Password is Correct.");
}else{
System.out.println("ID or Password is Incorrect.");
}
}
This Logic is very simple, but also come with some drawback, the only Advantage Compare to your code are:
Still able to do basic validation on User Input ID and Password.
Remove for loop and other unnecessary if else.
Only access database for once.
Hope this would help.
Yes, you could even do:
Select * from `users` where id = {id} and password = {password}
Also, to compare Strings in Java, you should use string1.equals(string2), not the == operator.
I am Trying to achieve single DB and multiple organization (not Multi tenancy) in ofbiz, how do i get user login Id till GenericDAO and append it to the query.
Please Suggest if you have any other ideas except multi tenancy!
Thanks
EDIT:
if (!conditions.isEmpty()) {
whereString.append(prefix);
whereString.append(EntityCondition.makeCondition(conditions, EntityOperator.AND).makeWhereString(modelEntity, whereEntityConditionParams, this.datasource));
}
System.out.println("************ whereString ************ "+whereString+" ---- ");
return whereString;
In line number 841 in my ofbiz v13.07 GenericDAO.java, i can get to know the place where query string is getting created. i want to access the session here to get the company Id and so i append it to the where clause. to get relevant data.
On my User class I have a field that is a list of strings:
#Persistent
private List<String> openIds;
When I create a new user I do this:
User user = new User();
user.openIds.add(openid);
pm.makePersistent(user);
When I break after that last line and look, the openIds contains the openid I put in there.
But, when I later call User user = pm.getObjectById(User.class, id); with the correct id, the openIds field is an empty list.
Anyone know what could cause that?
EDIT: BTW I'm running on the Google App Engine
UPDATE: Looking at the datastore viewer, I can see the openid was correctly stored in the database. So its just not getting it out correctly...
UPDATE 2: Its working fine now. I'm pretty sure I didn't change anything. I think what must have happened is that there was an old version of the user object being pulled from the database. A user object that was put in before I had the code that saves the openid. Once I wiped the database things worked fine.
Not putting that field in the fetch plan ?
Accessing persistent fields directly, rather than going via setters ?