Criei novos DAOs para a aplicaçao MyBooks usando o Space4J. Agora além de mysql o mybooks suporta também space4j, bastando para tal trocar as implementações dos DAOs (que são injetadas via IoC) no ApplicationManager.
A questão aqui é fazer um comparativo entre o approach usando banco de dados e o approach usando o Space4J. Também seria legal comparar com Hibernate ou JPA.
O objetivo é trocar idéias para chegar a uma conclusão se prevalência vale a pena ou não…
- MySql:
package org.mybooks.dao.mysql;
import java.util.*;
import java.sql.*;
import org.mybooks.dao.*;
import org.mybooks.bean.*;
public class MySQLUserDAO implements UserDAO {
private Connection conn = null;
public MySQLUserDAO() { }
public MySQLUserDAO(Connection conn) {
this.conn = conn;
}
public void setConnection(Connection conn) {
this.conn = conn;
}
public User loadById(int id) throws Exception {
PreparedStatement stmt = null;
ResultSet rset = null;
try {
stmt = conn.prepareStatement("select * from users where id = ?");
stmt.setInt(1, id);
rset = stmt.executeQuery();
if (rset.next()) {
User user = new User();
user.setId(id);
user.setUsername(rset.getString("username"));
user.setPassword(rset.getString("password"));
user.setName(rset.getString("name"));
user.setEmail(rset.getString("email"));
return user;
}
} finally {
if (rset != null) try { rset.close(); } catch(Exception e) { }
if (stmt != null) try { stmt.close(); } catch(Exception e) { }
}
return null;
}
public int insert(User user) throws Exception {
PreparedStatement stmt = null;
ResultSet rset = null;
try {
stmt = conn.prepareStatement("insert into users(username, password, name, email) values(?, ?, ?, ?)");
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
stmt.setString(3, user.getName());
stmt.setString(4, user.getEmail());
stmt.executeUpdate();
stmt.close();
stmt = conn.prepareStatement("select last_insert_id() from users");
rset = stmt.executeQuery();
if (rset.next()) {
int id = rset.getInt(1);
user.setId(id);
return id;
}
} finally {
if (rset != null) try { rset.close(); } catch(Exception e) { }
if (stmt != null) try { stmt.close(); } catch(Exception e) { }
}
return -1; // should never be called...
}
public void update(User user) throws Exception {
PreparedStatement stmt = null;
try {
stmt = conn.prepareStatement("update users set username = ?, password = ?, name = ?, email = ? where id = ?");
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
stmt.setString(3, user.getName());
stmt.setString(4, user.getEmail());
stmt.setInt(5, user.getId());
stmt.executeUpdate();
} finally {
if (stmt != null) try { stmt.close(); } catch(Exception e) { }
}
}
public void delete(User user) throws Exception {
PreparedStatement stmt = null;
try {
stmt = conn.prepareStatement("delete from users where id = ?");
stmt.setInt(1, user.getId());
stmt.executeUpdate();
} finally {
if (stmt != null) try { stmt.close(); } catch(Exception e) { }
}
}
public User loadByUsername(String username) throws Exception {
PreparedStatement stmt = null;
ResultSet rset = null;
try {
stmt = conn.prepareStatement("select id from users where username = ?");
stmt.setString(1, username);
rset = stmt.executeQuery();
int id = -1;
if (rset.next()) {
id = rset.getInt(1);
}
rset.close();
stmt.close();
if (id > 0) {
return loadById(id);
}
} finally {
if (rset != null) try { rset.close(); } catch(Exception e) { }
if (stmt != null) try { stmt.close(); } catch(Exception e) { }
}
return null;
}
public User loadByEmail(String email) throws Exception {
PreparedStatement stmt = null;
ResultSet rset = null;
try {
stmt = conn.prepareStatement("select id from users where email = ?");
stmt.setString(1, email);
rset = stmt.executeQuery();
int id = -1;
if (rset.next()) {
id = rset.getInt(1);
}
rset.close();
stmt.close();
if (id > 0) {
return loadById(id);
}
} finally {
if (rset != null) try { rset.close(); } catch(Exception e) { }
if (stmt != null) try { stmt.close(); } catch(Exception e) { }
}
return null;
}
public List searchUsersByName(List keywords, boolean and) throws Exception {
return searchUsersByName(keywords, and, -1);
}
public List searchUsersByName(List keywords, boolean and, int max) throws Exception {
Statement stmt = null;
ResultSet rset = null;
try {
StringBuffer sb = null;
if (keywords == null || keywords.size() == 0) {
sb = new StringBuffer("select id from users order by name");
} else {
sb = new StringBuffer(50 + 40 * keywords.size());
sb.append("select id from users where");
Iterator iter = keywords.iterator();
int index = 0;
while(iter.hasNext()) {
String token = (String) iter.next();
if (index++ != 0) sb.append(and ? " and" : " or");
sb.append(" lower(name) like '%").append(token.toLowerCase()).append("%'");
}
sb.append(" order by name");
if (max > 0) {
sb.append(" limit ").append(max);
}
}
stmt = conn.createStatement();
rset = stmt.executeQuery(sb.toString());
List ids = new LinkedList();
while(rset.next()) {
ids.add(new Integer(rset.getInt(1)));
}
rset.close();
stmt.close();
List users = new ArrayList(ids.size());
Iterator iter = ids.iterator();
while(iter.hasNext()) {
Integer id = (Integer) iter.next();
User user = loadById(id.intValue());
users.add(user);
}
return users;
} finally {
if (rset != null) try { rset.close(); } catch(Exception e) { }
if (stmt != null) try { stmt.close(); } catch(Exception e) { }
}
}
}
- Space4J:
package org.mybooks.dao.space4j;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.mybooks.bean.User;
import org.mybooks.dao.UserDAO;
import org.space4j.Space;
import org.space4j.Space4J;
import org.space4j.command.CreateMapCmd;
import org.space4j.command.PutCmd;
import org.space4j.command.RemoveCmd;
import org.space4j.indexing.Index;
import org.space4j.indexing.IndexManager;
import org.space4j.indexing.Key;
public class Space4JUserDAO implements UserDAO {
private static final String MAP_USERS = "users";
private static final String INDX_USERNAME = "indx_username";
private static final String INDX_EMAIL = "indx_email";
private Space4J space4j = null;
public Space4JUserDAO() { }
public Space4JUserDAO(Space4J space4j) {
this.space4j = space4j;
}
public void setSpace4j(Space4J space4j) {
this.space4j = space4j;
Space space = space4j.getSpace();
if (!space.check(MAP_USERS)) {
try {
space4j.exec(new CreateMapCmd<Integer, User>(MAP_USERS));
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException("Cannot create map: " + MAP_USERS, e);
}
}
IndexManager im = space4j.getIndexManager();
// create index by username...
if (!im.checkIndex(INDX_USERNAME)) {
Index indx = new Index(INDX_USERNAME, MAP_USERS, Index.TYPE.REGULAR, User.class, "username");
try {
im.createIndex(indx, space4j);
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException("Cannot create index: " + INDX_USERNAME, e);
}
}
if (!im.checkIndex(INDX_EMAIL)) {
Index indx = new Index(INDX_EMAIL, MAP_USERS, Index.TYPE.REGULAR, User.class, "email");
try {
im.createIndex(indx, space4j);
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException("Cannot create index: " + INDX_EMAIL, e);
}
}
}
public User loadById(int id) throws Exception {
Space space = space4j.getSpace();
Map map = (Map) space.get("users");
if (map == null) return null;
return (User) map.get(id);
}
public int insert(User user) throws Exception {
int id = space4j.getNextSeq("users_id_seq"); // will create if sequence does not exist...
user.setId(id);
int x = space4j.exec(new PutCmd(MAP_USERS, id, user));
return x;
}
public void update(User user) throws Exception {
space4j.exec(new PutCmd(MAP_USERS, user.getId(), user));
}
public void delete(User user) throws Exception {
space4j.exec(new RemoveCmd(MAP_USERS, user.getId()));
}
public User loadByUsername(String username) throws Exception {
IndexManager im = space4j.getIndexManager();
Index index = im.getIndex(INDX_USERNAME);
Map map = (Map) index.getMap();
return (User) map.get(username);
}
public User loadByEmail(String email) throws Exception {
IndexManager im = space4j.getIndexManager();
Index index = im.getIndex(INDX_USERNAME);
Map map = (Map) index.getMap();
return (User) map.get(email);
}
public List searchUsersByName(List keywords, boolean and) throws Exception {
return searchUsersByName(keywords, and, -1);
}
/*
* How to index something like this: name like '%carlos%' ????
*
* Is it a full table scan?
*
* Doing a full table scan using space4j...
*/
public List searchUsersByName(List keywords, boolean and, int max) throws Exception {
Space space = space4j.getSpace();
if (!space.check(MAP_USERS) || max == 0) new ArrayList(0);
Iterator iter = space.getSafeIterator(MAP_USERS);
Map<String, User> sorted = new TreeMap<String, User>();
while(iter.hasNext()) {
User u = (User) iter.next();
String name = u.getName().toLowerCase();
boolean matches = true;
if ((keywords == null || keywords.size() == 0)) {
matches = true; // list everything...
} else if (and) { // AND LOGIC
Iterator iter2 = keywords.iterator();
while(iter2.hasNext()) {
String keyword = ((String) iter2.next()).toLowerCase();
if (name.indexOf(keyword) == -1) {
matches = false;
break;
}
}
} else { // OR LOGIC
Iterator iter2 = keywords.iterator();
matches = false;
while(iter2.hasNext()) {
String keyword = ((String) iter2.next()).toLowerCase();
if (name.indexOf(keyword) != -1) {
matches = true;
break;
}
}
}
// check max...
if (matches) {
sorted.put(name, u);
if (max > 0 && sorted.size() == max) break;
}
}
List<User> results = new ArrayList<User>(sorted.size());
Iterator<User> iter3 = sorted.values().iterator();
while(iter3.hasNext()) {
results.add(iter3.next());
}
return results;
}
}