I am new to java programming and I am using databases to create a simple Bank Management system. I need to create user accounts with an account number with 9 digits, that does not start with 0. also, all the account numbers must be different(one account number can have repeating digits). Every time I run the program, it should give me a 9-digit number that is not stored in the 'accounts' table under 'account_number' in the 'login_info' database.
The program runs like this,
User goes to the login page
If he does not have an account he can go to the create account page
create account page has 3 tabs, Personnel info, bank account info, and online account info
user must fill out personnel info got be able to go to the bank account info
when the user goes to bank account info, it shows the previously filled items (Personel info) and a couple of additional items - Bank account type and account number
The account number must be generated when the user goes to the bank account info tab. The user cannot change the account number. (The account number must be one that has not been saved in the database before)This is the step I am stuck
After selecting the account type, the user can go to the online account info page and select a unique username and password
After that, the user can hit create account button to create his bank account along with the online account or he can exit the program if he is having second thoughts
When the user hit create account button, a query will run and insert data into MySQL tables. This is the point where the account is created.
The program runs beautifully, but I can't seem to generate a unique bank account number. Other steps are already completed.
(This is not for any commercial products, just a project I work on to get myself acquainted with database handling with java.)
Any Idea how to do this?
Thank you.
Here is an approach you could take, elaborating on my comments posted above:
pre-calculate all valid account numbers – there are a total of 3,265,920 valid combinations
9 choices for first digit: 1-9,
9 choices for 2nd digit: 0 is available, so 10 possible digits (0-9) except that something was used for the 1st digit
8 choices for 3rd, etc.
so: 9*9*8*7*6*5*4*3*2 combinations
populate each of those ~3 million numbers into the database table
include a "status" field to represent things like: "unclaimed", "pending", "claimed"
all account numbers start out as "unclaimed"
In your Java app, when you want to present the user with a candidate account number, you can use the database to update a single row from "unclaimed" to "pending" and return that account number – so the database would enforce correctness even if multiple callers simultaneously try to set up a new account. Something like: "update accounts where status=unclaimed set status=pending limit 1" and return the updated row.
From there:
If the user accepts the account number, simply change the status from "pending" to "claimed"
If they decline, change it back to "unclaimed"
This approach would allow you to do numeric specifics only once, up front, when creating all initial unclaimed accounts. It does have a potential drawback that you have 3 million rows sitting there unused, but there is a nice simplicity overall – no further combinations to worry about, or generating a number and then involving the database to see if that number is claimed or not (and re-generating if number in use), or any kind of scanning through the database to use as input for the number selecting process, or whatever other ideas people might come up with. Just do the work up front.
If you want the number to be random, create a number from 0 to 899 999 999 and then add 100 000 000 (so the first will never be 0). If the numbers are stored in an Arraylist (in this case called nums), the following code should help:
int num;
Do{
num = (int)(Math.random()*800000000)+100000000;
}while (nums.contains(num));
nums.add(num);
I am using databases to create a simple Bank Management system. I need
to create user accounts with an account number with 9 digits, that
does not start with 0. also, all the account numbers must be
different. Every time I run the program, it should give me a 9-digit
number that is not stored in the 'accounts' table under
'account_number' in the 'login_info' database.
This actually turns out to be an unexpectedly complicated question to answer. The best answer depends upon other factors which you have not mentioned:
Does the account number have to be unique "each time the program is run" or "each time an account number is requested during the same run (but not necessarily from run to run)"?
Is this a single-threaded environment (i.e., how many simultaneously executing threads might be trying to create account numbers at the same time)?
Does the account number have the sense of identity; does it need to be able to uniquely identify a specific account at all times (or are there times, perhaps when the account is being created from a form, when an account doesn't need to have identity?
What manages the identity? Your program system? The database that you are using to store the information?
If the first bullet item answer is "each time the program is run", then you need to think about how the account number seed (the quantity or quantities that are used to generate your next available account number) is persisted from run to run (the seed otherwise is destroyed when the JVM exits).
If the second bullet item is "multiple threads", then you need to think about how to prevent the same account number from being inadvertently provided to threads requesting one at the same time.
The remaining bullet items deal with identity. Account numbers are generally used to identify specific accounts to the system (but not necessarily). So, you have to consider when the identity needs to become available to the system. You also have to think about what system is responsible for managing the identity. If the identity is needed as soon as an account entity is created, then it needs to be obtained during the instantiation of the account by Java. If it is not needed until the account entity is persisted to the database, then it may be possible for the database system to create the identity.
A hybrid solution would be to persist the account as soon as it was instantiated, and then read it right back again to obtain the account number (at the cost of increasing database traffic). Logic might be needed to delete the database record if the account did not need to be persisted after all (because, say, it had been canceled).
Depending on the answers to these questions, and upon other important factors such as availability, scalability, redundancy, security etc., the complete solution to the original problem could become arbitrarily complex.
But if we assume that account numbers need to be unique only during the same run of the Java system and that account accesses are only single threaded, then a solution could become very simple:
public static class AccountNumberManager {
private static long accountNumberSeed = getStartupSeedValue();
private AccountNumberManager() { }
public long getNextAccountNumber() {
return ++accountNumberSeed;
}
private static long getStartupSeedValue() {
return 100000000L;
}
}
Some brief notes:
A static class for account number management makes the initialization of the account number seed value thread safe. The initial value initialization occurs while the class is locked by the class loader during the loading process and is therefore thread safe (the class and its static fields can only be initialized once and once only). This is the static holder class initialization method. This would be handy if the system ever evolved into a concurrent environment.
This solution, of course, assumes that the account number is needed when the account entity is initialized. I think this is a good practice anyway. My bias is that database systems should not be used to create system-wide identitifiers when possible (only to persist them).
It is not a best practice to use account numbers as database primary keys. This is an opinion that is fairly widely, not but universally, held.
Related
I have table named - College and Student
I want to generate unique Enrollment number for the student at the time of registration
In single College there are multiple registrations are possible at the same time For example College - ABC have many persons who can register student
My logic for generate Enrollment id is YY_College-Pk_Last-five-digit-increment
YY_COLFK_DDDDD
At the registration time of student I will first fire Max query like
select Max(Enrollment_No) from student where College_Fk=101
And get last Enrollment_No and split last five digit and increment by 1 and insert it
When there is a chance to submit two students' data at the same time there is chance of generating single Enrollment_No for two students
How to manage this problem
On the Java side of things you could draw some inspiration from concepts such as UUIDs (see https://www.baeldung.com/java-uuid for example).
But as you are using a database, you should rather use the capabilities of that part, see How to generate unique id in MySQL? for some examples.
In other words: the database is your single source of truth. It offers you the ability to have IDs that are guaranteed to be unique!
if you want to add two student data at same time then u must be using insert statement twice, so for each data you have to yo
I am wondering what is the pattern for this. I am building an application where users can create their accounts. And once a user creates her account she gets some basic data set up such as amount of money, name of her cat, and other complex objects.
What is the best way to handle these default values?
One way is to hard code them in the Account bean. However, what happens if these default values ever have to change in production?
One naive way is to have the default values in the settings and then copy them into the Account bean when creating each user.
Though things get messy when these default values differ by user groups. For instance if the user is from Europe, I want to set her initial amount of money to 54 Euros. If she is from the US, I want to set it to -20 US Dollars. And if the user is from China, I want to assign 20 initial cars to her while assigning 10 buildings if the user is from Mexico.
As you can see these initial setup for each user can comprise some complex objects.
What is the best way/pattern to handle this in Java and Spring?
Properties file is a good solution. A database would be more initial cost but perhaps provide better long value. You can account for the difference in values per user group by having grouped properties, such as
us.initial_value=-20
us.unit=USD
eu.initial_value=54
eu.unit=Euros
china.initial_valu=20
china.unit=cars
You could have the code provide a default value for the default, in case the value isn't read in from the file correctly.
In my App I'm modelling an Invoice. In my country (Italy) every invoice must have a unique sequential number without holes, that every year have to restart from 1.
I thought long and hard about the best way to implement it but I have not found a good guide about this. For now I have a JpaRepository where I've my custom synchronized save() method in which I get the last id used:
SELECT MAX(numero) FROM Invoice WHERE YEAR(date) = :year
The problem of this approach is that is not very safe because the developer should know that the save should be done only with that particular service.
Instead I'd like more an approach that is hidden to the developer.
I thought to use a #Prepersist method in a #EntityListeners. This sounds good but do get entity manager inside this class is not so simple....so maybe is not the optimal place...
Finally I thought about Hibernate Interceptor....
Please give me some hints. The problem seems a quite generic problem; so maybe there is yet a good practice to follow.
Thanks
This problem can be broken down into the following requirements:
Sequentially unique: Generate numbers in a sequence, starting from a given value (say, 1000001) and then always incrementing by a fixed value (say, 1).
No gaps: There must not be any gaps between the numbers. So, if the first number generated is 1000001, the increment is 1 and 200 numbers have been generated so far, the latest number should be 1000201.
Concurrency: Multiple processes must be able to generate the numbers at the same time.
Generation at creation: The numbers must be generated at the time of creation of a record.
No exclusive locks: No exclusive locks should be required for generating the numbers.
Any solution can only comply with 4 out of these 5 requirements. For example, if you want to guarantee 1-4, each process will need to take locks so that no other process can generate and use the same number that it has generated. Therefore, imposing 1-4 as requirements will mean that 5 will have to be let gone of. Similarly, if you want to guarantee 1, 2, 4 and 5, you need to make sure that only one process (thread) generates a number at a time because uniqueness cannot be guaranteed in a concurrent environment without locking. Continue this logic and you will see why it is impossible to guarantee all of these requirements at the same time.
Now, the solution depends on which one out of 1-5 you are willing to sacrifice. If you are willing to sacrifice #4 but not #5, you can run a batch process during idle hours to generate the numbers. However, if you put this list in front of a business user (or a finance guy), they will ask you to comply with 1-4 as #5 is a purely technical issue (to them) and therefore they would not want to be bothered with it. If that is the case, a possible strategy is:
Perform all possible computation required to generate an invoice upfront, keeping the invoice number generation step as the very last step. This will ensure that any exceptions that can occur, happen before the number is generated and also to make sure that a lock is taken for a very short amount of time, thereby not affecting the concurrency or performance of the application too much.
Keep a separate table (for example, DOCUMENT_SEQUENCE) to keep a track of the last generated number.
Just before saving an invoice, take an exclusive row-level lock on the sequence table (say, isolation level SERIALIZABLE), find the required sequence value to use and save the invoice immediately. This should not take too much time because reading a row, incrementing its value and saving a record should be a short enough operation. If possible, make this short transaction a nested transaction to the main one.
Keep a decent-enough database timeout so that concurrent threads waiting for a SERIALIZABLE lock do not time out too fast.
Keep this whole operation in a retry loop, retrying at least 10 times before giving up completely. This will ensure that if the lock queue builds up too fast, the operations are still tried a few times before giving up totally. Many commercial packages have retry count as high as 40, 60 or 100.
In addition to this, if possible and allowed by your database design guidelines, put a unique constraint on the invoice number column so that duplicate values are not stored at any cost.
Spring gives you all the tools to implement this.
Transactions: Through the #Transactional annotation.
Serialization: Through the isolation attribute of the #Transactional annotation.
Database access: Through Spring JDBC, Spring ORM and Spring Data JPA.
Retries: Through Spring Retry.
I have a sample app that demonstrates using all these pieces together.
I have a datastore that stores the cab booking details of the customers. In the admin console I need to display the statistics to the admin, like busiest location, peak hours, total bookings in a particular location in a particular day. For the busiest location i need to retrieve the location from where most number of cabs has been booked. Should I iterate through the entire datastore and keep a count or is there any method to know which location has maximum and minimum duplicates.
I am using a ajax call to java servlet which should return the busiest location.
And I also need a suggestion for maintaining such a stats page. Should I keep a separate Entity kind just for counters and stats and update it everytime when a customer books a cab or is the logic correct for iterating through the entire datastore for the stats page. Thanks in advance.
There are too many unknowns about your data model and usage patterns to offer a specific solution, but I can offer a few tips.
Updating a counter every time you create a new record will increase your writing costs by 2 write operations, which may or may not be significant.
Using keys-only queries is very cheap and fast. It is the preferred method for counting something, so you should try to model your data in such a way that a keys-only query can give you an answer. For example, if a "trip" entity has a property for "id of a starting point", and this property is indexed, you can loop through your locations using a keys-only query to count the number of trips that started from each location.
Assuming that you record a lot of trips, and that an admin page will be visited/refreshed not very frequently, the keys-only queries approach is the way to go. If the admin page is visited/refreshed many times per hour, you may be better off with the counters.
I am working on the backend of a game. Players first purchase their tickets, which are stored into the database, then they play and can win certain prizes. Each player can buy a max of 60 tickets.
A new requirement appeared, setting an upper bound for the total number of tickets per game - 10 000 tickets. The implementation would involve adding to the purchase endpoint a test checking that the total number of purchased tickets at that time + number of tickets required on current purchase is less or equal to the max number of tickets for that game, in order for a purchase to be accepted.
The problem is that, calculating the current number of purchased tickets by using count on the tickets table, the returned value may be out-of-date because in the meantime other players could have purchased tickets.
A possible solution is to lock the tickets table during the purchase, but this can have a negative impact on performance and user experience. Please let me know if you have a different idea.
If yours is a hard constraint then you must avoid multiple purchases being conducted concurrently. Probably an appropriate table lock in the DB is the best way to accomplish such serialization. There could be other alternatives (i.e. performing the serialization somewhere in the front end), but they are likely to be messier to implement, more prone to bugs, and worse-performing.
In fact, it may be difficult to make your game exhibit consistent behavior at all without appropriate locking in the DB. On the other hand, you probably don't need explicit locking. If you configure your database with an appropriate transaction isolation level then it should do all necessary locking for you.
Since there's no clear win to be had here, I recommend shelving the performance question until you can actually test your performance. If it turns out not to be good enough then you can determine from actual measurement what parts of the system can most benefit from tuning.