Adding two numbers from the database in the Spring Service layer - java

I have an entity called User which holds three fields:
ID No1
1 5
2 4
Then I have a UserRepository which extends JpaRepository, thus including crud operations.
I want to be able to take value 5 and 4 and add them together.
This logic should be applied in the Service layer.
So I have a AddService interface and AddServiceImpl which implements that interface.
public interface AddService{
public void addNumbers(user1, user2);
}
public class AddServiceImpl implements AddService{
public void addNumbers(user1, user2){
List<User> user1=userRepository.findOne(1);
List<User> user2=userRepository.findOne(2);
// how do I take those specific values that are on the field No?
}
}
How do I implement this Service so that it adds those numbers?
I need to inject the repository and save a list with the data from user1 and user2 and then add them? But how do I do that?

try this code and let me know if this what you want
public Integer addNumbers(user1, user2){
List<User> user1=userRepository.findOne(1);
List<User> user2=userRepository.findOne(2);
Integer number1 = user1.getNo();
Integer number2 = user2.getNo();
return number1 + number2;
}
If the user1.getNo() or if user2.getNo() could be null please take car of this as well. I do not know in this case what you want to return.
In addition ,change the interface to return an Integer
public interface AddService{
public Integer addNumbers(user1, user2);
}

Why do you need a list of type User ? Anyway, what you should do is iterate over the list and for each User object in your list get the numbers using the getter of that field. You must have the getters and setters for all the fields on your entity class, this way you can get the value of your instance variables on your repository class.

user1.getID() and user1.getNo() without the user class it’s hard to tell. Same thing for user2. Could you provide User for us?
findOne shouldn’t have a list in return type. It should be unique.
The calls to the repository shouldn’t be in your addNumbers method because your users are in the method parameters.

Related

JDBC dao and inheritance

Let's say I have 2 classes in my model :
public class Account {
int capital;
int numero
}
public class SavingAccount extends Account{
double rate;
}
So when I have to save or retrieve an account in a database using JDBC, it works but for the binding it is OK for capital and numero but for rate I need to check the type and cast it :
if(account.getType() == AccountType.SAVINGACCOUNT) {
((SavingAccount)Account).setRate(result.getDouble("rate"));
}
Is it possible to do otherwise than that or than have 2 different methods ?
The last and just-before-implementation class is the SavingAccount. SavingAcccount contains rate's getter and setter methods. So, whenever you use getRate(), you should type cast your Account to SavingAccount, because in the heap space of SavingAccount you have getRate() method.
Because the final implementation is via SavingAccount, you also provide via TypeChecking AccountType.SAVINGACCOUNT for the correct database transactions.
When you do your executions via Account instance, it gives you polymorphic power. That's why it's important.
So, in your scenario, I don't see any other solution exists. You are doing good.

Hibernate - AttributeConverter and custom SQL function

I'm trying to map EnumSet into a single value as integer via Hibernate.
I have implemented AttributeConverter:
public class RolesToIntConverter implements AttributeConverter<Set<Roles>, Integer> {
#Override
public Integer convertToDatabaseColumn(Set<Roles> attribute) {
return Roles.encode(attribute);
}
#Override
public Set<Roles> convertToEntityAttribute(Integer dbData) {
return Roles.decode(dbData);
}
}
As well as new SqlDialect:
public class LocalSqlDialect extends MySQL5Dialect {
public LocalSqlDialect() {
super();
registerFunction("bitwise_and", new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 & ?2)"));
}
}
Then I call it like this:
public Collection<PersonsEntity> getAll(Roles roles) {
Query q = getEntityManager().createQuery("SELECT s FROM PersonsEntity AS s WHERE ( bitwise_and(s.roles,:roles) <> 0 )");
q.setParameter("roles", EnumSet.of(roles));
List<PersonsEntity> result = (List<PersonsEntity>) q.getResultList();
return result;
}
This causes several issues:
ClassCastException, because for some reason, it passes set to the AttributeConverter per each element
I tried changing type from Set<Roles> to Object (at the converter), and then using instanceof I checked whether it is a single object or a set and parsed accordingly. After that I found out, that while calling s.roles = :roles worked fine, calling the registered bitwise function did not even call the AttributeConverter
ResultSet exception, because after calling bitwise function and using as input Set with two values, it actually puts ?, ? into the query instead of calling AttributeParser, which should merge it into a single number
The question is, what em I doing wrong? Or do you know a better solution to a problem: map EnumSet into a single database column, while being able to assign multiple roles to one entity.
For example I have value 1 for user, value 2 for manager, value 4 for admin, etc.. I want a particular person to be a user and a manager at the same time, which would mean value 3 (1 | 2) and then I want to find him when searching for user only (resp. manager only) via number 1 (resp. 2) - which suggests bitwise and.
Thank you in advance for any response!

Android Realm copyToRealmOrUpdate creates duplicates of nested objects

I have following classes:
public class Note extends RealmObject {
#PrimaryKey
private String id;
private Template template;
// other primitive fields, getters & setters
}
public class Template extends RealmObject {
private String name;
private String color;
// other primitive fields, getters & setters
}
I get my data from backend via Retrofit & Gson, so I have ready-to-use java objects in response.
Let's imagine that backend returns me same three Notes each time I call it.
When I get the list of Note objects, I do the following:
private void fetchNotesAndSave() {
List<Notes> notes = getNotesViaRetrofit();
Realm realm = Realm.getInstance(mContext);
realm.beginTransaction();
realm.copyToRealmOrUpdate(notes);
realm.commitTransaction();
realm.close();
}
After that I call these lines to check count of stored objects:
int notesCount = mRealm.where(Note.class).findAll().size();
int templatesCount = mRealm.where(Template.class).findAll().size();
For the first time:
notesCount == 3;
templatesCount == 3;
That's right. But, if I call the server again, get same notes (same primaryKey ids), and call fetchNotesAndSave() again, I'll get these results:
notesCount == 3;
templatesCount == 6;
Each time I call copyToRealmOrUpdate(), nested objects, that are inside of objects with primaryKey are duplicated - not updated.
Is there any way to change this behaviour?
Please let me know if you need more information. Thanks in advance!
It is because your Template class doesn't have any primary key. In that case these objects are inserted again as there is no guarantee that the referenced template objects safely can be updated, even if they are part of another object that has a primary key.
If you add a #PrimaryKey to your template class it should work as you expect it to.
If you can't provide a PK as suggested, you might want to use the following work around to avoid duplicates.
for (Note note: notes) {
realm.where(Note.class)
.equalTo("id", note.getId())
.findFirst()
.getTemplate()
.deleteFromRealm();
}
realm.copyToRealmOrUpdate(notes);

How to optimize this OO design in Hibernate ORM?

Based on object-oriented approach, I write the following entities:
#Entity
public class Customer {
#Id
private String id;
#OneToMany
private List<Order> orders;
public BigDecimal getTotal() {
// iterate over orders and sum the total
BigDecimal total = BigDecimal.ZERO;
for (Order o: orders) {
total = total.add(o.getTotal());
}
return total;
}
... // getter & setter
}
#Entity
public class Order {
#Id
private String id;
private BigDecimal total;
...
}
I realized that when calling getTotal() method for a Customer, Hibernate will issue a SELECT * FROM Order query to retrieve all Orders. The number of Order will surely increase as years passed. I believe a SELECT SUM(o.total) FROM Order o will give a better performance, CMIIMW. I just don't know where should I put the query? Rules of object oriented design suggest that getTotal() should be part of Customer, but the framework I'm using (Spring Transaction) doesn't allow transaction in domain objects.
In the first case, select * from orders.
You are just getting the list of orders and you need to calculate the sum in Server side code with iterating over the orders.
In the second case, select sum(o.total) from orders where order.customer_ id = 1234;
Database is doing the calculation for you. In terms of performance also,
this is better.
Why the database needs to delegate to some upper layer, when It can do it.
So I suggest you with the second case only.
As per OO, It might suggest to encapsulate both properties and related methods.
But its a Domain Class, which gets directly mapped to fields in Database.
To separate Data Access Logic, We can have a separate layer i.e DAO and put the desired logic in it.

Java Inheritance and avoiding constant use of instanceof

I have three classes, an abstract User and two specific: NormalUser which holds an ArrayList of one or more Address objects which can be different (domestic, international, custom etc.) and then the Admin class which has a method which returns true . They both contain more methods which are unrelated to each other.
abstract class User{
public User(String username, String pw){
...
}
public class NormalUser extends User{
...
private ArrayList<Address> addresses;
...
public void addAdress(ArrayList<Address> address){
addresses.addAll(address);
}
public class Admin extends User{
...
public boolean getIsAdmin(){
return true;
}
}
Now in another class if I make 4 user objects like this for example:
ArrayList<User> users;
users.add(new NormalUser( "1", "pw");
users.add(new NormalUser( "2", "pw");
users.add(new NormalUser( "3", "pw");
users.add(new NormalUser( "4", "pw");
users.add(new Admin("5", "pw"));
users.add(new NormalUser( "6", "pw");
And say I want to use the addAddress method in NormalUser, then I have to downcast the specfic user in users to NormalUser, before I can use the addAddress method in NormalUser like this:
if (user instanceof NormalUser){
NormalUser normal = (NormalUser) user;
normal.addAddress(...)
}
The reason why I would like both NormalUser and Admin to be a User is so I can process them together when logging in.
I thought of adding the addEmail to the User class and then overriding it in the NormalUser class, but I would have to do that for every method in the NormalUser class, plus Admin would inherit it from the User as well, when it doesnt need that functionality.
Question 1: Is there a better way to do this as I heard using instanceof is a bad thing? and I would have to use instanceof every time I use a method that is specific to the NormalUser class.
Quesiton 2: Is an ArrayList of object Addresses the best way to link the RegularUser to specific addresses/(Objects)?
There is no database involved right now.
So for example user a has 2 addresses one domestic and one international, and user b just has a domestic address, user c has a domestic and a custom address etc.
Thanks.
PS. I've searched the previous posts extensively but havent found a solution. In both my Java books they both show examples of using instanceof but no mention of it being a bad practice.
You can use the Visitor pattern - a bit clumsy and slightly unreadable, but probably the best solution for your problem.
Actually your solution with pushing addEmail to base class isn't that bad. Simply provide an empty implementation in base User and override in RegularUser. If you want to check whether given User instance supports adding e-mails, provide another method like supportsAddEmail returning false by default and true when overriding addEmail.
I think that the easiest solution is to create a class UserList that would contain a list of NormalUser and a list of Admin. An instance of the class UserList would replace the original list. The class UserList could provide some methods such as:
User getUser(index i) // implemented with the two lists
User removeUser(index i) // implemented with the two lists
NormalUser getNormalUser(index i) // implemented with the normal user list
NormalUser removeNormalUser(index i) // implemented with the normal user list
Admin getAdmin(index i) // implemented with the admin user list
Admin removeAdmin(index i) // implemented with the admin user list
....
All the code for handling the appropriate lists would be encapsulated in the UserList class. You could have methods that use both lists or only one list, depending on what you need to do with the users. Classes that interact with UserList would not know if there is only a single or two lists inside UserList.

Categories

Resources