Il bug è stato risolto.
Lunga vita al forum!! Lunga vita al ré!!

Ci speravate, vero, che questo progetto di libertà di espressione fallisse? E invece non è così, perché quando Mattia introduce un bug è capace di ripararlo, mentre voi siete qui a starnazzare.
Ora però voglio proprio vedere quanto sono bravi due snowflake, che fanno tanto i fighi.
In questo thread perciò cercheremo di capire l'errore e sicuramente i due snowflake saranno in grado di spiegarlo.
Ecco come si presentava il metodo quando dava problemi...
public List<String> getForums() {
String query = "select forums.id\n" +
"from forums\n" +
"left join messages on forums.id=messages.forum\n" +
"and forums.enabled=1\n" +
"group by forums.id\n" +
"order by count(forums.id) desc;";
Connection conn = null;
ResultSet result = null;
PreparedStatement stat = null;
try {
conn = dataSource.getConnection();
stat = dataSource.getConnection()
.prepareStatement(query);
result = stat.executeQuery();
List<String> res = new ArrayList<String>();
while(result.next()) {
res.add(result.getString("id"));
}
return res;
} catch (SQLException e) {
return null;
}
finally {
CloseDbResources(conn, stat, result);
}
}Le risorse unmanaged vengono ripulite.
protected void CloseDbResources(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) { }
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) { }
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) { }
}
}Le classe MiscDAO (che contiene la query) viene istanziata dalla DAOFactory, che è un singleton. Il metodo init (che inizalizza la classe per interfacciarsi al database) viene chiamato una solo una volta, nel momento in cui la classe viene istanziata... e siccome il metodo init è privato, siamo sicuri che non possa essere chiamato da fuori.
static synchronized DAOFactory getInstance() {
if (instance == null) {
String persistenceName = FdTConfig.getProperty("persistence.name");
try {
instance = new DAOFactory();
instance.init(FdTConfig.getDatabaseConfig(persistenceName));
} catch (Exception e) {
LOG.fatal("Cannot instantiate Persistence '" + persistenceName + "'", e);
return null;
}
}
return instance;
}void init(Properties databaseConfig) throws ClassNotFoundException {
String driver = databaseConfig.getProperty("driverclass");
Class.forName(driver);
String username = databaseConfig.getProperty("username");
String password = databaseConfig.getProperty("password");
String url = databaseConfig.getProperty("url");
dataSource = new BasicDataSource();
dataSource.setMaxTotal(15);
dataSource.setMaxIdle(10);
dataSource.setMinIdle(3);
dataSource.setMaxWaitMillis(30000);
dataSource.setTestOnBorrow(true);
dataSource.setTestWhileIdle(true);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setValidationQuery("SELECT 1");
dataSource.setValidationQueryTimeout(30);
DSLContext jooq = DSL.using(dataSource, SQLDialect.MYSQL);
authorsDAO = new AuthorsDAO(jooq);
threadsDAO = new ThreadsDAO(jooq);
messagesDAO = new MessagesDAO(jooq);
pollsDAO = new PollsDAO(jooq);
quotesDAO = new QuotesDAO(jooq);
bookmarksDAO = new BookmarksDAO(jooq);
adminDAO = new AdminDAO(jooq);
miscDAO = new MiscDAO(jooq, dataSource);
privateMsgDAO = new PrivateMsgDAO(jooq);
digestDAO = new DigestDAO(jooq);
loginsDAO = new LoginsDAO(jooq);
}Per risolvere il bug (speriamo) è stato in pratica sufficiente riscrivere il metodo getForums in questa maniera, cioè utilizzando JOOQ.
public List<String> getForums() {
Result<Record1<String>> records = jooq.select(FORUMS.ID)
.from(FORUMS)
.leftOuterJoin(MESSAGES)
.on(FORUMS.ID.eq(MESSAGES.FORUM))
.groupBy(FORUMS.ID)
.orderBy(DSL.count(FORUMS.ID).desc())
.fetch();
List<String> res = new ArrayList<String>(records.size());
for (Record1<String> record : records) {
res.add(record.getValue(FORUMS.ID));
}
return res;
}Ora, a me interessa MOLTO capire l'errore commesso nella precedente versione, perché sbagliando e analizzando l'errore si impara.
Sono curioso di sentire la spiegazione del frocetto snowfloake e dello svizzero strapagato per fare database di merda.