4

I have found myself in the need to override a static method, simply because it makes most sense, but I also know this is not possible.

The superclass, Entity.java:

abstract public class Entity<T> {
    public Entity() {
        //set up database connection
    }

    abstract public static Map<Object, T> getAll();

    abstract public void insert();

    abstract public void update();

    protected void getData(final String query) {
        //get data via database
    }

    protected void executeQuery(final String query) {
        //execute sql query on database
    }
}

One of the many concrete implementations, Account.java:

public class Account extends Entity<Account> {
    private final static String ALL_QUERY = "SELECT * FROM accounts";
    private final static String INSERT_QUERY = "INSERT INTO accounts (username, password) VALUES(?, ?)";
    private final static String UPDATE_QUERY = "UPDATE accounts SET password=? WHERE username=?";

    private String username;
    private String password;

    public Account(final String username, final String password) {
        this.username = username;
        this.password =  password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(final String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(final String password) {
        this.password = password;
    }

    @Override
    public static Map<Object, Account> getAll() {
        //return a map using the ALL_QUERY string, calls getData(string);
    }

    @Override
    public void insert() {
        //insert this using INSERT_QUERY, calls executeQuery(string);
    }

    @Override
    public void update() {
        //update this using UPDATE_QUERY, calls executeQuery(string);
    }
}

I haven't been going in depth explaining the code, but any general feedback on it would also be appreciated, I hope the comments explain enough.

So basically I think we can all agree that using Account.getAll() makes more sense over new Account().getAll() (if I would introduce a dummy syntax for it). However I do want to have it extend the Entity class, currently it is only for convienience, but later on I may have to use sets/lists/multisets of Entity and perform an update() action on all of them, for example if I would build some queue that performances all updates every minute.

So well, is there a way to construct getAll() correctly?

Regards.

user207421
  • 305,947
  • 44
  • 307
  • 483
skiwi
  • 66,971
  • 31
  • 131
  • 216
  • Just remove the `@Override` on the static method, and you're fine. See also: http://stackoverflow.com/q/548861/139010 – Matt Ball May 13 '13 at 19:52
  • Thankyou for using my suggestions. Not marking the answer you used as correct might lead other attention to your original question though. – christopher May 13 '13 at 19:52
  • @MattBall Implementation wise it is fine indeed. But I rather have some harsher restrictions, that is the reason I mention it in the interface in the first place. @ChrisCooney Probably that's some lag as I did mark it as correct, I hope I've used your suggestions correctly, especially with the generic argument `Entity` – skiwi May 13 '13 at 19:55
  • 3
    Read up on Martin Fowler's Table Data Gateway and Data Mapper patterns. You should also read up on Data Access Objects. Remove persistence data from your POJOs. – Sotirios Delimanolis May 13 '13 at 19:59
  • How can getAll abstract and static in Entity? – zw324 May 13 '13 at 20:21
  • I'm a little concerned about your database design. It is a best practice to create a class that models the data in your database tables and then use that as an important part of your Database Access Object (DAO). DAO's serve the important role of separating the concerns of data access and the concerns of your application that works with the data. Is that the kind of design pattern you are working with here? – scottb May 13 '13 at 20:24
  • You don't 'extend' methods. Do you mean 'override'? – user207421 May 14 '13 at 02:00
  • This would be a good time to use/ switch to Hibernate. The problems & questions are only going to get harder, from here. – Thomas W May 14 '13 at 02:11

2 Answers2

1

You could have separate classes for operations on all elements:

abstract public class Collection<T extends Entity<T>> {
    abstract public static List<T> getAll();
    public void printAll() {
        // Print all entries of List obtained from getAll()
    }
}

Which you could use as:

public class Accounts extends Collection<Account> {
    @Override
    public List<Account> getAll() {
        //return a list using the ALL_QUERY string, calls getData(string);
    }
}
ValarDohaeris
  • 6,064
  • 5
  • 31
  • 43
  • It's not a Collection, it's a Data Access Object/Service. (Or, as the answer below called it, a Repository). Usage, API & functionality are _quite quite different_ from Java or other collections. – Thomas W May 14 '13 at 02:12
  • I just called it `Collection` for lack of a better name, a name that doesn't interfere with existing collection classes would indeed be better. – ValarDohaeris May 14 '13 at 06:52
1

It doesn't seems to me that it is really "simply because it makes most sense".

Tying persistence at your entity is not a good idea. There are already lots of patterns that give an appropriate design on this problem.

For example, in Domain Driven Design, "Persistence Ignorance" is what people trying to achieve. Consider making a Repository for each of your entity:

interface Repository<T> {
    List<T> findAll();
    void insert(T);
    void update(T);
}

so you can override it by whatever way you want:

interface UserRepository extends Repository<User> {
    // some other methods which is meaningful for User
    User findByLoginName(String loginName);
}


class UserRepositoryImpl implements UserRepository {
    List<User> findAll() {
         // call whatever query
    }
    void insert(T){...}
    void update(T){...}
    User findByLoginName(String loginName) {...}
}

With a proper design and a component to handle the retrieval/storage of entity, you can have a less-persistence-coupled entity, and with repository that can perform proper "overriding".

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
  • I quite like "Repository" for the naming (thanks Adrian!). I'd +1'd this answer, but in general I would recommend using _Hibernate_ rather than spending 2 man-years writing a persistence layer. Wrinkles & traps aplenty, if you try to DIY this.. – Thomas W May 14 '13 at 02:14
  • @ThomasW You know what? A lot of people is using Hibernate in implementing repositories :) And, take a look in Spring Data - Hibernate, which makes creating Repository a breeze :) Hibernate is easy to use, but it doesn't mean that it is fine to pollute the entities with persistence logics (which use Hibernate) – Adrian Shum May 14 '13 at 02:47