1

The enum I'm using uses String's, but the database uses int. It's relatively simple to create a look-up from within the State enum to return an integer. However, the lookup only works one way, to get an integer from a state. Do I need a wrapper class which takes integers and returns a State?

The database stores the State as an int, and I don't want to change that.

package net.bounceme.dur.server.db;

import org.apache.commons.dbcp.BasicDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.bounceme.dur.data.State;
import net.bounceme.dur.data.Title;
import net.bounceme.dur.server.streams.MyProps;

public class Queries {

    private static final Logger log = Logger.getLogger(Queries.class.getName());
    private final MyProps p = new MyProps();
    private Connection connection = null;

    public void connect() throws SQLException {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(p.getDbDriver());
        dataSource.setUrl(p.getDbUrl());
        dataSource.setUsername(p.getDbUser());
        dataSource.setPassword(p.getDbPassword());
        connection = dataSource.getConnection();
    }

    public List<Title> selectTitles() throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        connect();
        PreparedStatement statement = connection.prepareStatement("SELECT * FROM titles.titles");
        ResultSet resultSet = statement.executeQuery();
        Title title = null;
        List<Title> titles = new ArrayList<>();
        while (resultSet.next()) {
            title = new Title();
            title.setId(resultSet.getInt(1));
            title.setCreated(resultSet.getTimestamp(2));
            title.setPhone(resultSet.getInt(3));
            title.setTitle(resultSet.getString(4));
            int state = resultSet.getInt(5);
            State s;
            title.setState(State.a);
            title.setState(State.undefined);
            titles.add(title);
        }
        return titles;
    }

    public void updateTitle(Title clientTitle) {
        try {
            connect();
            String updateString
                    = "update titles.titles "
                    + "set STATE = ? where ID = ?";
            try (PreparedStatement ps = connection.prepareStatement(updateString)) {
                log.info(clientTitle.toString());
                ps.setInt(1, clientTitle.getState().getCode());
                ps.setInt(2, clientTitle.getId());
                ps.executeUpdate();
            }
        } catch (SQLException ex) {
            Logger.getLogger(Queries.class.getName()).log(Level.SEVERE, null, ex);
        }
        log.info("...updated...?");
    }
}




package net.bounceme.dur.data;

public enum State {

    undefined(0), x(1), o(2), c(3), a(4), l(5), d(6);
    private int code = 0;

    State(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

    public State getState() {
        switch (code) {
            case 0:
                return State.undefined;
            case 1:
                return State.x;
            case 2:
                return State.o;
            case 3:
                return State.c;
            case 4:
                return State.a;
            case 5:
                return State.d;
            case 6:
                return State.l;
            default:
                return State.undefined;
        }
    }
}

Something like:

   State stateFromInt = StateUtils.getState(i);

but then I need a StateUtils class, and that just seems like a hassle. I fully realize it's possible to make the database store String data, and parse that back into a state, but that's not the solution I'm asking for.

Flexo
  • 87,323
  • 22
  • 191
  • 272
Thufir
  • 8,216
  • 28
  • 125
  • 273

1 Answers1

2

Just add a static method to State called fromCode(int code):

public static State fromCode(int code) {
    switch (code) {
        // ...
    }
}

This is a common factory method pattern. In your code, you can can then just call:

title.setState(State.fromCode(resultSet.getInt(5)));

You can then even refactor your existing getState() method to also make use of the same static method (even though the getState() method seems not to have any real practical use).

Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
  • 1
    That non-static `getState()` seems odd anyway. Why not just `return this` (which makes the whole method redundant). – Thilo Jul 07 '14 at 04:15
  • I'd rather see a mapper. This couples magic numbers in the DB to the enum. A mapper, on the other hand, is supposed to have intimate knowledge of both entities. – David Ehrmann Jul 07 '14 at 04:22
  • @DavidEhrmann I cannot think of a more efficient and visible mapper than an enum declaration. – Robby Cornelissen Jul 07 '14 at 04:26
  • these comments about magic numbers and mappers are exactly what I'm asking about. I'll try this code -- thanks. – Thufir Jul 07 '14 at 04:32