views:

133

answers:

5

I need to apply a check so that a user cannot register using an email id which already exists in the database.

+1  A: 

Put a unique constraint on the relevant column in the database table. For example (MySQL):

ALTER TABLE Users ADD UNIQUE (Email)

edit - If the e-mail field is already a primary key as you write in a comment above, then you don't need this, because primary keys are by definition unique. Then in Java you could catch the SQLException that you get if you'd insert a record with a primary key that already exists, or you can do a SELECT ... WHERE Email=? before you try the insert to see if there is already a record with that e-mail address.

Jesper
+8  A: 

Put a constraint on the email column, or select before insert.

Jason
+1 - *"or select before insert"* ... in the same transaction!
Stephen C
+1 - Enforce data constraints at the database level whenever possible (or practical).
Mark Peters
+1 This is the right way to solve it
Federico Cristina
+2  A: 

Probably something like this DAO method :

public boolean isDuplicateEntry(String email) {
        Session session = getSession();
        try {
            User user = (User) session.get(User.class, email);
            session.close();

            return (null != user);

        } catch (RuntimeException e) {
            log.error("get failed", e);
            session.close();
            throw e;
        }
    }
c0mrade
I would recommend putting session.close() in a finally block. Not that its a huge deal but this is a classic example where you would want to use a finally block in my opinion.
tkeE2036
where should i put this code?
bhavna raghuvanshi
@tkeE2036 you are right, @bhavna raghuvanshi you should put it somewhere where your DAO classes are
c0mrade
thankyou.....i did it
bhavna raghuvanshi
A: 

you may: - make the email field unique, try to insert adn catch the exception or - make a select before each insert

kgb
+2  A: 

There are indeed basically two ways to achieve this:

  1. Test if record exists before inserting, inside the same transaction. The ResultSet#next() of the SELECT should return false. Then do INSERT.

  2. Just do INSERT anyway and determine if SQLException#getSQLState() of any catched SQLException starts with 23 which is a constraint violation as per the SQL specification. It can namely be caused by more factors than "just" a constraint violation. You should namely not handle every SQLException as a constraint violation.

    public static boolean isConstraintViolation(SQLException e) {
        return e.getSQLState().startsWith("23");
    }
    

I would opt for the first way as it is semantically more correct. It is in fact not an exceptional circumstance. You namely know that it is potentially going to happen. But it may potentially fail in heavy concurrent environment where transactions are not synchronized (either unawarely or to optimize performance). You may then want to determine the exception instead.


That said, you normally don't want to put a PK on an email field. They are namely subject to changes. Rather use a DB-managed autogenerated PK (MySQL: BIGINT UNSIGNED AUTO_INCREMENT, Oracle/PostgreSQL: SERIAL, SQLServer: IDENTITY) and give the email field an UNIQUE key.

BalusC
I would prefer the second to avoid two calls to the database. Agree with you about the email field. Not a good candidate for a primary key.
HLGEM
@HLGEM: A query on an indexed field is cheap. Creating an exception is expensive. I am not sure. Profile before microoptimizing or just don't microoptimize at all ;)
BalusC
Exception should hit very rarely so it can be more expensive, one hit to the database vice two, happens with every insert. Ergo, it will in the long run be more expensive. But you are right when faced with multiple choices, it is a good idea to profile.
HLGEM