I need to make a servlet service that does following things
when user request the service, servlet generates a unique 5 letter string that has never been generated. (combination of 0~9 and a~Z)
if user accepts it, save user's info using the unique string(that #1 generated) as a primary key
First thing popped in my head was using static class variable that increments by 1 as requests hit servlet, but searching here and google says this is really really bad idea, as if multiple users hit the service at the same time, it will break...
and now I am clueless what to look into.
What would be the best and the safetest approach to generate a unique string incrementally?
Add a field sequence no in table and when ever a new request comes get the highest sequence number from database and then add one ie plus 1 and save it
According to this site, your highest number (ZZZZZ) is 426088025. In the database world you'd want to used a sequence but, because of your 5 character restriction, you need to make sure that it doesn't go over this number (hopefully you're storing less than 426M records).
To create a sequence you'll do something like:
create sequence your_sequence maxvalue 426088025 no cycle
That is the PostgreSQL syntax - your database may vary.
Then, in your code you can do a
select nextval('your_sequence')
to get your value and then Base64 encode this value. In PostgreSQL the "no cycle" means that if you get to the max it will throw an error.
In Java 8, Base64 is included:
import java.util.Base64;
...
String userNumber = Base64.getEncoder().encodeToString(Integer.toString(integerFromSequenceSelect));
Otherwise, if you're stuck with an old version of Java, use Apache Commons Codec and run:
import org.apache.commons.codec.binary.Base64;
...
String userNumber = Base64.encodeBase64String(Integer.toString(integerFromSequenceSelect));
Related
How to get sequence number for WT.Part or Wt.Document in Windchill through API?
When I create WT.Part - number automatically generated. But I can not find any method that returns the next number. I'm using Info*Engine.
At the time of object WTPart creation windchill use OOTB oracle_seqence in order to auto generate the number.
The sequence name is mentioned in the OIR of respective object.
Like
For
WTPart it is : WTPARTID_seq
For
WTDocument it is : WTDOCUMENTID_seq
etc .
So, if you want to get next number of WTPart then you can directly call the method wt.fc.PersistenceHelper.manager.getNextSequence("WTPARTID_seq");
from your info*engine task.
For different object the name of the sequence will be different.
In 10.2 PTC introduce another method getCurrentSequence("SEQ_NAME") to get the current sequence value without incrementing the same.
Are you familar with using Java with InfoEngine? If so, you can get the sequence by:
wt.fc.PersistenceHelper.manager.getNextSequence("SEQUENCE_NUMBER_OF_YOUR_OBJECT")
The sequence number will be specified inside the "Object Initialization Rule" that is associated with your object type.
As a temporary solution - create a new Part, read the number and either use it or delete.
i'm creating a Itemcode for my inventory system i want the number system of integer values like this using java
for example this
for group 1 the code would be 001 -
0010001,
0010002
for group 2 the code would be 002-
0020003,
0020004
for group 3 the code would be 003-
0030005,
0030006
the items are encoded individually so when i add a new entry it will detect which group it belongs to and generate it desired item code the first 3 digits will be the corresponding Value identification in which group it belongs to the the next 4 digit code will just be the increment value..and would be stored as one integer using MySQL database
You need to decide:
Are the item codes to be represented as: one integer, a pair of integers (group & item), a string ... or something else.
Is the numbering scheme per the first example or the second one. (You seem to have chosen one scheme now ...)
How you are going to populate the items and codes. Do you read the codes? Do you generate them all in one go while loading items from a file. Do you create items and item ids one at a time (e.g. interactively).
How is this information going to be "stored"? In memory only? In a flat file? In a database? (MySQL ... ?)
These decisions will largely dictate how you implement the item id "generation".
Basically, your problem here is that >>you<< need to figure out what the requirements are. Once you have done that, the set of possible solutions will reduce to a manageable size, and you can then either work it out for yourself or ask a sensible question.
First of all, question is not about ignoring white spaces at the beginning or end of the strings so it is not a duplicate.
I have a mobile field in database that its values are in different formats such as xxx xxx xxx, xxxxxxxxx, x xxx xxx xx etc, how can I make hibernate criteria to ignore the patterns of strings?
For example, lets say the number in database is 344 555 666
344555666 is failed
344 555 666 is failed
344 is true (first three digits that do not have space in database!)
However, there is no doubt that all numbers are provided and all aforementioned values should return 344 555 666 as their results.
Another example would be as following:
Lets say a user searches for all phone numbers that includes 12345; then DB returns following results 12345678, 12345987 and 12345768 now I need to format these three numbers that are returned by DB before showing to the user.
Code
...
private String mobile;
....
Hibernate
.add(Restrictions.ilike("user.mobile", number);
PVR's answer is useful,but how about if in future I needed to add a new format like XXX-XXX-XXX or X-XXXX-XXXX-XXXX ? Please also note there is only one field that user uses to enter the search value.
Try using following..
criteria.add(Restrictions.ilike(
user.mobile, number, MatchMode.ANYWHERE));
Edit :
I meant that if the format of the no. in the database can only be one amongst XXX XXX XXXX / XXXXXXXXXX then we need to write a specific logic which checks both of the formats availability in database.
number1 : in format of XXX XXX XXXX
number2 : in format of XXXXXXXXXX
criteria.add(Restrictions.or(Restrictions.ilike(
user.mobile, number1, MatchMode.ANYWHERE),(Restrictions.ilike(
user.mobile, number2, MatchMode.ANYWHERE)));
Facing such problem, I usually reverse it. Currently, you have in a single column of your database (mobile) values in different formats (xxx xxx xxx, xxxxxxxxx, x xxx xxx xx etc.) and it is hard to make search on that column.
You should still allow input of mobile numbers in all those formats, but carefully rewrite them in one single format say 12345679 before writing them in database. This way that reformatting occurs only when inserting new records or on updates, and I assume you will have much more read accesses than write ones.
If you allready have records in your database, you should considere using a batch to transform them in one single operation .
Once you have only one format, you can put an index on the column as it could speed select queries by orders of magnitude as soon as you have thousands of records.
When you want to do a search, allow any format for user input of what they want, and apply same transformation that you apply on insert. For example if a user presents 123 456 789 or 123-456-789 or any of your accepted format, in your code for search transform it in 123456789 and do you query with that value (using the index ...)
From user point of view, you still allow he to present input as he wants, and simply the responses may come faster. The only drawback is that you will display not the value he entered but a standardized version of it.
From your point of view (as the programmer) you get something simpler to write and to maintain with less stress on database.
did you try Projections.sqlProjection
You can use replace REPLACE(mobile, ' ') inside
I know this is an answer that could eat up your db resources, you can
test it and check if it matches your need.
I've done phone number formatting before, but, the solution you are looking for could be difficult, if you have to search using regex I'll construct a regex in the code and search in the db. (Oracle has regex_like function, you may want to use that instead of ilike of hibernate)
eg phone number from client +333 555 9999, phone number in db: +3 33 555 9999
Construct the following regex based on what client sends:
/+(\s-.)*3(\s-.)*3(\s-.)*3(\s-.)*5(\s-.)*5(\s-.)*5(\s-.)*9(\s-.)*9(\s-.)*9(\s-.)*9(\s-.\d\w)*/
What you are saying is there could be many (.) dots may (\s) spaces many (-) hiphens in a phone number trailing with many(.\s-\d\w) (eg: x234 or ext2342)
As per your conversation with PVR, it seems like the format of the phone number can be anything.
Hibernate framework is based on patterns. It cannot handle any format on its own.
Its advisable to not include the phone number based criteria in Hibernate. You must execute your entire criteria query without the phone number and thereafter you must have java logic for filtering rest of the results.
However, the best solution is make your design more solid. Adding constraint on the format of the phone is the best practice. You can consider adding a validation on format of phone.
You can write your own Criterion by implementing the Criterion interface.
In your toSqlString method just use the replace function of your database. AFAIK replace(str, needle, replacement) is a SQL99 standard function so it should work in todays dbms.
I've been wondering what's the correct practice for generating unique ids? The thing is in my web app I'll have a plugin system, when a user registers a plugin I want to generate a unique serial ID for it. I've been thinking about storing all numbers in a DB or a file on the server, generating a random number and checking whether it already exists in the DB/file, but that doesn't seem that good. Are there other ways to do it? Would using the UUID be the preferred way to go?
If the ids are user-facing, which it seems they are, then you want them to be difficult to guess. Use the built-in UUID class, which generates random ids for you and can format them nicely for you. Extract:
UUID idOne = UUID.randomUUID();
UUID idTwo = UUID.randomUUID();
log("UUID One: " + idOne);
log("UUID Two: " + idTwo);
Example output:
UUID One: 067e6162-3b6f-4ae2-a171-2470b63dff00
UUID Two: 54947df8-0e9e-4471-a2f9-9af509fb5889
There are other solutions in the link provided. I think it compares the methods quite well, so choose the one which best suits your needs.
Another interesting method is the one MongoDB uses, but this is possibly overkill for your needs:
A BSON ObjectID is a 12-byte value
consisting of a 4-byte timestamp
(seconds since epoch), a 3-byte
machine id, a 2-byte process id, and a
3-byte counter. Note that the
timestamp and counter fields must be
stored big endian unlike the rest of
BSON
If they weren't user facing, then you could just leave it to the database to do an auto-incrementing id: 1, 2, 3, etc.
Why not go for a static (or, in this case, a context-scoped) AtomicInteger that would be incremented when a plugin is registered ?
You could base it on user ID and timestamp, ensuring uniqueness but also providing a certain "readability"? E.g. User ID = 101, timestamp = 23 Dec 2010 13:54, you could give it ID:
201012231354101
or
101201012231354
The alternative UUID is obviously guaranteed to be unique but takes up a lot of DB space, and is quite unwieldy to work with.
A final idea is to ask your central DB for a unique ID, e.g. Oracle has sequences, or MySQL uses AUTO_INCREMENT fields, to assign unique integers.
I'm having a little trouble using Hibernate with a char(6) column in Oracle. Here's the structure of the table:
CREATE TABLE ACCEPTANCE
(
USER_ID char(6) PRIMARY KEY NOT NULL,
ACCEPT_DATE date
);
For records whose user id has less than 6 characters, I can select them without padding the user id when running queries using SQuirreL. I.E. the following returns a record if there's a record with a user id of "abc".
select * from acceptance where user_id = "abc"
Unfortunately, when doing the select via Hibernate (JPA), the following returns null:
em.find(Acceptance.class, "abc");
If I pad the value though, it returns the correct record:
em.find(Acceptance.class, "abc ");
The module that I'm working on gets the user id unpadded from other parts of the system. Is there a better way to get Hibernate working other than putting in code to adapt the user id to a certain length before giving it to Hibernate? (which could present maintenance issues down the road if the length ever changes)
That's God's way of telling you to never use CHAR() for primary key :-)
Seriously, however, since your user_id is mapped as String in your entity Hibernate's Oracle dialect translates that into varchar. Since Hibernate uses prepared statements for all its queries, that semantics carries over (unlike SQuirreL, where the value is specified as literal and thus is converted differently).
Based on Oracle type conversion rules column value is then promoted to varchar2 and compared as such; thus you get back no records.
If you can't change the underlying column type, your best option is probably to use HQL query and rtrim() function which is supported by Oracle dialect.
How come that your module gets an unpadded value from other parts of the system?
According to my understanding, if the other part of the system don't alter the PK, they should read 6 chars from the db and pass 6 chars all along the way -- that would be ok. The only exception would be when a PK is generated, in which case it may need to be padded.
You can circumvent the problem (by trimming or padding the value each time it's necessary), but it won't solve the problem upfront that your PK is not handled consistently. To solve the problem upfront you must eiher
always receive 6 chars from the other parts of the module
use varchar2 to deal with dynamic size correctly
If you can't solve the problem upfront, then you will indeed need to either
add trimming/padding all around the place when necessary
add trimming/padding in the DAO if you have one
add trimming/padding in the user type if this works (suggestion from N. Hughes)