REST&GAE: How to define a getter without using resource Id - java

I am using Google App Engine with Cloud Endpoints to code a simple API. That API only has one entity: Book, with fields Long id and String name.
The Google Plugin for Eclipse generated for me an API class which has a getBook(Long id) method. However, I would also like to be able to get a book knowing its name. That is to say I would like to also have a getBookByName(String name) method. Could you show me a simple code for it, or a link which shows something like that? I think I have to use the JDO framework with a query object.
Here is the API class code:
#Api(name = "bookendpoint")
public class BookEndpoint {
/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method and paging support.
*
* #return A CollectionResponse class containing the list of all entities
* persisted and a cursor to the next page.
*/
#SuppressWarnings({ "unchecked", "unused" })
#ApiMethod(name = "listBook")
public CollectionResponse<Book> listBook(
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
PersistenceManager mgr = null;
Cursor cursor = null;
List<Book> execute = null;
try {
mgr = getPersistenceManager();
Query query = mgr.newQuery(Book.class);
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
HashMap<String, Object> extensionMap = new HashMap<String, Object>();
extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
query.setExtensions(extensionMap);
}
if (limit != null) {
query.setRange(0, limit);
}
execute = (List<Book>) query.execute();
cursor = JDOCursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (Book obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<Book> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}
/**
* This method gets the entity having primary key id. It uses HTTP GET method.
*
* #param id the primary key of the java bean.
* #return The entity with primary key id.
*/
#ApiMethod(name = "getBook")
public Book getBook(#Named("id") Long id) {
PersistenceManager mgr = getPersistenceManager();
Book book = null;
try {
book = mgr.getObjectById(Book.class, id);
} finally {
mgr.close();
}
return book;
}
/**
* This inserts a new entity into App Engine datastore. If the entity already
* exists in the datastore, an exception is thrown.
* It uses HTTP POST method.
*
* #param book the entity to be inserted.
* #return The inserted entity.
*/
#ApiMethod(name = "insertBook")
public Book insertBook(Book book) {
PersistenceManager mgr = getPersistenceManager();
try {
if (book.getId() != null) {
if (containsBook(book)) {
throw new EntityExistsException("Object already exists");
}
}
mgr.makePersistent(book);
} finally {
mgr.close();
}
return book;
}
/**
* This method is used for updating an existing entity. If the entity does not
* exist in the datastore, an exception is thrown.
* It uses HTTP PUT method.
*
* #param book the entity to be updated.
* #return The updated entity.
*/
#ApiMethod(name = "updateBook")
public Book updateBook(Book book) {
PersistenceManager mgr = getPersistenceManager();
try {
if (!containsBook(book)) {
throw new EntityNotFoundException("Object does not exist");
}
mgr.makePersistent(book);
} finally {
mgr.close();
}
return book;
}
/**
* This method removes the entity with primary key id.
* It uses HTTP DELETE method.
*
* #param id the primary key of the entity to be deleted.
*/
#ApiMethod(name = "removeBook")
public void removeBook(#Named("id") Long id) {
PersistenceManager mgr = getPersistenceManager();
try {
Book book = mgr.getObjectById(Book.class, id);
mgr.deletePersistent(book);
} finally {
mgr.close();
}
}
private boolean containsBook(Book book) {
PersistenceManager mgr = getPersistenceManager();
boolean contains = true;
try {
mgr.getObjectById(Book.class, book.getId());
} catch (javax.jdo.JDOObjectNotFoundException ex) {
contains = false;
} finally {
mgr.close();
}
return contains;
}
private static PersistenceManager getPersistenceManager() {
return PMF.get().getPersistenceManager();
}
}

Overloading is not supported. You should just call your functions "getBookByName", "getBookByISBN", etc...

Related

Is there a way to obtain the keys from a deleted record?

I'm using PostgreSQL to save a form in three tables, one for the name and id, another one for the fields to populate, and a third to store values for the fields.
private static final String REMOVE_FORM = "DELETE FROM forms WHERE name = ?";
private PreparedStatement removeFormQuery;
public boolean connect() throws SQLException{
this.connection = DriverManager.getConnection(URL);
this.removeFormQuery = this.connection.prepareStatement(REMOVE_FORM);
}
public void close() throws SQLException {
if(null != this.connection) {
this.connection.close();
}
if(null != this.removeFormQuery) {
this.removeFormQuery.close();
}
}
private void removeForm(String form) {
try {
removeFormQuery.setString(1, form);
int execute = removeFormQuery.executeUpdate();
System.out.println(execute);
ResultSet generatedKeys = removeFormQuery.getGeneratedKeys();
while (generatedKeys.next()) {
int anInt1 = generatedKeys.getInt("id");
removeFieldQuery.setInt(1, anInt1);
if (removeFieldQuery.execute())
System.out.println("remove field failed");
else
System.out.println("remove field success");
ResultSet generatedFieldsKeys = removeFieldQuery.getGeneratedKeys();
while (generatedFieldsKeys.next()) {
int anInt = generatedFieldsKeys.getInt("id");
removeListItemQuery.setInt(1, anInt);
if (removeListItemQuery.execute())
System.out.println("remove listItem failed");
else
System.out.println("remove listItem success");
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
The code doesn't generate keys after the remove query is executed, am I missing something?
While you haven't told us what queries you are running, if they are deletes then you wouldn't expect any generated keys.
From the Javadoc for Statement.getGeneratedKeys():
* Retrieves any auto-generated keys created as a result of executing this
* Statement object. If this Statement object did
* not generate any keys, an empty ResultSet
* object is returned.
Keys may be auto generated when you insert into a table, creating a new row which needs a primary key, but when you delete a row no key generation occurs.

PreparedStatement.executeUpdate() doesn't insert in sqlite database

i'm trying to make a DAO class for my Java project.
I've a SQLite Database with only one table "USER".
The schema is:
CREATE TABLE USER(
username VARCHAR(20) NOT NULL PRIMARY KEY,
password VARCHAR NOT NULL,
total_matches INTEGER DEFAULT 0,
victories INTEGER DEFAULT 0,
times_alien INTEGER DEFAULT 0,
times_human INTEGER DEFAULT 0,
total_steps INTEGER DEFAULT 0,
humans_killed INTEGER DEFAULT 0,
aliens_killed INTEGER DEFAULT 0,
kills_as_human INTEGER DEFAULT 0,
kills_as_alien INTEGER DEFAULT 0,
total_escapes INTEGER DEFAULT 0,
total_broken_hatches INTEGER DEFAULT 0,
total_noises INTEGER DEFAULT 0,
online_status VARCHAR(5) NOT NULL DEFAULT "false");
My UserDAOImpl class has findAll(), findByNickname(String nickname), insert, update, delete methods.
I use PreparedStatementto prevent SQL Injection.
My Issue is that if I call my insert(User toInsert) method and then cycle through the findAll() result, I can see the right insertion.
But if I go to the Terminal and open the DB with the SQLite command line, when I execute "SELECT * FROM USER", the previous insertion doesn't shows.
The DB Class:
/**
* The Class DB.
* Gives a connection to the game Database.
*/
public class DB {
/** the singleton instance of the Database. */
private static DB instance = new DB();
/** the path to the database. */
private static final String DBPath = "db/eftaios_DB.db";
/**
* Istantiates a new Database.
*/
private DB(){
/*
*
*/
}
/**
* Create a connection between this class and the database files.
*
* #return the database connection.
* #throws SQLException the SQL exception
*/
public Connection connect() throws SQLException{
Connection dbConnection = null;
try {
Class.forName("org.sqlite.JDBC");
String dbPath = DB.class.getClassLoader().getResource(DBPath).getPath();
dbConnection = DriverManager.getConnection("jdbc:sqlite:"+dbPath);
} catch (ClassNotFoundException e) {
/*
* do nothing, the class is imported in the maven dependencies
*/
} catch (SQLException e) {
throw new SQLException();
}
return dbConnection;
}
The DAO Class is:
/**
* The class UserDAOImpl implements the UserDAOInterface
* It implements a DAO (Data Access Object) for the User table.
* It gives access to the User table on the Database.
* With this class you can perform queries like find, insert, delete and update on the USER table.
*/
public class UserDAOImpl implements UserDAOInterface {
/** the database connection used to query it. */
private Connection dbConnection;
/** the result of a query to the database. */
private ResultSet queryResult;
/** the statement to execute to perform db queries. */
private Statement queryStatement;
/** the prepared statement to execute mysql injection secure queryes. */
private PreparedStatement queryPreparedStatement;
/** the name of the database user's table. */
private static final String USER_TABLE = "USER";
/**
* To user list.
*
* #param qryResult the qry result
* #return the list
* #throws SQLException the SQL exception
*/
private List<User> toUserList(ResultSet qryResult) throws SQLException{
List<User> result = new ArrayList<User>();
/* forall user in result, populate the new user and add it to the users list */
while(qryResult.next()){
User record = new User();
record.setNickname(qryResult.getString(User.NICKNAME_COL_NAME));
record.setPassword(qryResult.getString(User.PASSWORD_COL_NAME));
record.setAliensKilled(qryResult.getInt(User.ALIENS_KILLED_COL_NAME));
record.setHumansKilled(qryResult.getInt(User.HUMANS_KILLED_COL_NAME));
record.setKillsAsAlien(qryResult.getInt(User.KILLS_AS_ALIEN_COL_NAME));
record.setKillsAsHuman(qryResult.getInt(User.KILLS_AS_HUMAN_COL_NAME));
record.setOnlineStatus(qryResult.getBoolean(User.ONLINE_STATUS_COL_NAME));
record.setTimesAlien(qryResult.getInt(User.TIMES_ALIEN_COL_NAME));
record.setTimesHuman(qryResult.getInt(User.TIMES_HUMAN_COL_NAME));
record.setTotalBrokenHatches(qryResult.getInt(User.TOTAL_BROKEN_HATCHES_COL_NAME));
record.setTotalEscapes(qryResult.getInt(User.TOTAL_ESCAPES_COL_NAME));
record.setTotalMatches(qryResult.getInt(User.TOTAL_MATCHES_COL_NAME));
record.setTotalNoises(qryResult.getInt(User.TOTAL_NOISES_COL_NAME));
record.setTotalSteps(qryResult.getInt(User.TOTAL_STEPS_COL_NAME));
record.setVictories(qryResult.getInt(User.VICTORIES_COL_NAME));
result.add(record);
}
return result;
}
/*
* (non-Javadoc)
* #see it.polimi.ingsw.deolacremona.server.model.database.UserDAOInterface#findAll()
*/
#Override
public List<User> findAll() throws SQLException {
String findAllQuery = "SELECT * FROM "+USER_TABLE;
List<User> users = new ArrayList<User>();
this.dbConnection = DB.getDatabase().connect();
this.dbConnection.setAutoCommit(false);
this.queryStatement = this.dbConnection.createStatement();
this.queryResult = this.queryStatement.executeQuery(findAllQuery);
users = this.toUserList(queryResult);
this.dbConnection.commit();
this.queryResult.close();
this.queryStatement.close();
this.dbConnection.close();
return users;
}
/*
* (non-Javadoc)
* #see it.polimi.ingsw.deolacremona.server.model.database.UserDAOInterface#findByNickname(java.lang.String)
*/
#Override
public List<User> findByNickname(String userNickname) throws SQLException {
String findByNicknameQuery = "SELECT * FROM "+USER_TABLE+" WHERE "+User.NICKNAME_COL_NAME+"=?";
List<User> users = new ArrayList<User>();
this.dbConnection = DB.getDatabase().connect();
this.dbConnection.setAutoCommit(false);
/* preparing the statement to prevent sql injection */
this.queryPreparedStatement = this.dbConnection.prepareStatement(findByNicknameQuery);
this.queryPreparedStatement.setString(1, userNickname);
/* now get the result */
this.queryResult = this.queryPreparedStatement.executeQuery();
users = this.toUserList(queryResult);
this.dbConnection.commit();
this.queryPreparedStatement.close();
this.queryResult.close();
this.dbConnection.close();
return users;
}
/*
* (non-Javadoc)
* #see it.polimi.ingsw.deolacremona.server.model.database.UserDAOInterface#insert(it.polimi.ingsw.deolacremona.server.model.database.User)
*/
#Override
public boolean insert(User toInsert) throws SQLException {
boolean result = false;
MD5Hasher hasher = new MD5Hasher();
String md5Password = hasher.md5(toInsert.getPassword());
String insertQuery =
"INSERT INTO "+USER_TABLE+" ("+User.NICKNAME_COL_NAME+","+User.PASSWORD_COL_NAME+") VALUES (?,?)";
this.dbConnection = DB.getDatabase().connect();
this.dbConnection.setAutoCommit(false);
/* preparing the statement to prevent sql injection */
this.queryPreparedStatement = this.dbConnection.prepareStatement(insertQuery);
this.queryPreparedStatement.setString(1, toInsert.getNickname());
this.queryPreparedStatement.setString(2, md5Password);
if(this.queryPreparedStatement.executeUpdate()==1)
result = true;
this.queryPreparedStatement.close();
this.dbConnection.commit();
this.dbConnection.close();
return result;
}
/*
* (non-Javadoc)
* #see it.polimi.ingsw.deolacremona.server.model.database.UserDAOInterface#update(it.polimi.ingsw.deolacremona.server.model.database.User)
*/
#Override
public boolean update(User toUpdate) throws SQLException {
boolean result = false;
String updateQuery = "UPDATE "+USER_TABLE+" SET "
+ User.ALIENS_KILLED_COL_NAME +"=?,"
+ User.HUMANS_KILLED_COL_NAME +"=?,"
+ User.KILLS_AS_ALIEN_COL_NAME +"=?,"
+ User.KILLS_AS_HUMAN_COL_NAME +"=?,"
+ User.ONLINE_STATUS_COL_NAME +"=?,"
+ User.TIMES_ALIEN_COL_NAME +"=?,"
+ User.TIMES_HUMAN_COL_NAME +"=?,"
+ User.TOTAL_BROKEN_HATCHES_COL_NAME +"=?,"
+ User.TOTAL_ESCAPES_COL_NAME +"=?,"
+ User.TOTAL_MATCHES_COL_NAME +"=?,"
+ User.TOTAL_NOISES_COL_NAME +"=?,"
+ User.TOTAL_STEPS_COL_NAME +"=?,"
+ User.VICTORIES_COL_NAME +"=?"
+ " WHERE "+User.NICKNAME_COL_NAME+"=?";
/* preparing the sql statement to prevent sql injection */
this.dbConnection = DB.getDatabase().connect();
this.dbConnection.setAutoCommit(false);
this.queryPreparedStatement = this.dbConnection.prepareStatement(updateQuery);
this.queryPreparedStatement.setInt (1, toUpdate.getAliensKilled());
this.queryPreparedStatement.setInt (2, toUpdate.getHumansKilled());
this.queryPreparedStatement.setInt (3, toUpdate.getKillsAsAlien());
this.queryPreparedStatement.setInt (4, toUpdate.getKillsAsHuman());
this.queryPreparedStatement.setBoolean(5, toUpdate.isOnlineStatus());
this.queryPreparedStatement.setInt (6, toUpdate.getTimesAlien());
this.queryPreparedStatement.setInt (7, toUpdate.getTimesHuman());
this.queryPreparedStatement.setInt (8, toUpdate.getTotalBrokenHatches());
this.queryPreparedStatement.setInt (9, toUpdate.getTotalEscapes());
this.queryPreparedStatement.setInt (10, toUpdate.getTotalMatches());
this.queryPreparedStatement.setInt (11, toUpdate.getTotalNoises());
this.queryPreparedStatement.setInt (12, toUpdate.getTotalSteps());
this.queryPreparedStatement.setInt (13, toUpdate.getVictories());
this.queryPreparedStatement.setString (14, toUpdate.getNickname());
if(this.queryPreparedStatement.executeUpdate()==1){
result = true;
}
this.queryPreparedStatement.close();
this.dbConnection.commit();
this.dbConnection.close();
return result;
}
/*
* (non-Javadoc)
* #see it.polimi.ingsw.deolacremona.server.model.database.UserDAOInterface#updateAdder(it.polimi.ingsw.deolacremona.server.model.database.User)
*/
#Override
public boolean updateAdder(User toUpdate) {
// TODO Auto-generated method stub
return false;
}
/*
* (non-Javadoc)
* #see it.polimi.ingsw.deolacremona.server.model.database.UserDAOInterface#delete(it.polimi.ingsw.deolacremona.server.model.database.User)
*/
#Override
public boolean delete(User toDelete) throws SQLException {
boolean result = false;
String deleteQuery = "DELETE FROM "+USER_TABLE+" WHERE username=?";
this.dbConnection = DB.getDatabase().connect();
this.dbConnection.setAutoCommit(false);
this.queryPreparedStatement = this.dbConnection.prepareStatement(deleteQuery);
this.queryPreparedStatement.setString(1, toDelete.getNickname());
if(this.queryPreparedStatement.executeUpdate()==1){
result = true;
}
this.queryPreparedStatement.close();
this.dbConnection.commit();
this.dbConnection.close();
return result;
}
}
My test main method is:
public static void main(String[] args) throws SQLException, UnknownHostException{
DB database = DB.getDatabase();
database.connect();
MD5Hasher h = new MD5Hasher();
UserDAOImpl d = new UserDAOImpl();
User s = new User();
s.setNickname("davide");
s.setPassword("ciao");
if(d.insert(s))
System.out.println("insert");
// d.delete(s);
for(User x : d.findAll()){
System.out.println("Nickname: "+x.getNickname()+" password: "+x.getPassword()+" matches: "+x.getTotalMatches());
}
}
Thank you for your time.
EDIT: when I cut the database and put it into another directory, exit eclipse, move back the database in his previous directory and reopen eclipse, then all the changes that Java done previously are lost. –
SOLVED: In a Maven Project, all the resources are copied into another directory after the "build" command. I was reading the wrong db.

spring-data-couchbase error while finding all documents with PageRequest

Using Spring Data Couchbase I created a very simple repository
public interface UserDao extends PagingAndSortingRepository<User, String>
This should allow me to execute a paged findAll as follows:
Page<User> userResult = repo.findAll(new PageRequest(1, 20));
However the the following is always thrown:
Exception in thread "main" java.lang.IllegalStateException: Unknown query param: Page request [number: 1, size 20, sort: null]
at org.springframework.data.couchbase.repository.query.ViewBasedCouchbaseQuery.execute(ViewBasedCouchbaseQuery.java:47)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:337)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.couchbase.repository.support.ViewPostProcessor$ViewInterceptor.invoke(ViewPostProcessor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at $Proxy14.findAll(Unknown Source)
at com.polycom.cloudAxis.proxymanagement.model.Main.main(Main.java:41)
This doesn't happen if I create a Query and use the skip/limit/startKeyDocId, but would like to use PagingAndSortingRepository if possible.
Any idea what could be wrong? Thanks for all friendly help :)
i also had this same issue, here was the approach i took. its actually a very small change to the core implementation (which currently only support Query object types), essentially all I did was add another instance of check:
if (param instanceof Query) {
query = (Query) param;
} else if (param instanceof Pageable) {
pageable = (Pageable) param;
}
then added the logic for paging here, its been working so far but i havent fully vetted it so any comments from the community would be appreciated.
if (pageable != null) {
CouchbaseClient client = operations.getCouchbaseClient();
View view = client.getView(designDocName(), viewName());
// Paginator p = new Paginator(client, view, query,
// pageable.getPageSize());
Paginator paginator = client.paginatedQuery(view, query, pageable.getPageSize());
// now we need to goto the start point
ViewResponse viewResponse = null;
// views are 0 base
int i = 0;
while (paginator.hasNext()) {
viewResponse = paginator.next();
if (pageable.getPageNumber() == i++) {
LOGGER.debug("Found the response for this page: {} ", i);
break;
}
}
if (viewResponse == null) {
LOGGER.debug("no view response so leaving now");
return null;
}
Class<?> type = method.getEntityInformation().getJavaType();
final List result = new ArrayList(viewResponse.size());
for (final ViewRow row : viewResponse) {
result.add(operations.findById(row.getId(), type));
}
return result;
}
To get this wired up i had to do some things i didnt want to :D, i wanted to just override one method however to get to it required me to override many other things, so i ended up copying a little bit of code, ideally i would like to get this added as part of https://jira.spring.io/browse/DATACOUCH-93
And the whole impl here:
public class DCORepositoryFactory extends CouchbaseRepositoryFactory {
CouchbaseOperations couchbaseOperations;
MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext;
public DCORepositoryFactory(CouchbaseOperations couchbaseOperations) {
super(couchbaseOperations);
mappingContext = couchbaseOperations.getConverter().getMappingContext();
this.couchbaseOperations = couchbaseOperations;
}
#Override
protected Object getTargetRepository(RepositoryMetadata metadata) {
// TODO Auto-generated method stub
CouchbaseEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
final DCORepository simpleCouchbaseRepository = new DCORepository(entityInformation, couchbaseOperations);
simpleCouchbaseRepository.setViewMetadataProvider(ViewPostProcessor.INSTANCE.getViewMetadataProvider());
return simpleCouchbaseRepository;
}
#Override
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key) {
return new CouchbaseQueryLookupStrategy();
}
/**
* Currently, only views are supported. N1QL support to be added.
*/
private class CouchbaseQueryLookupStrategy implements QueryLookupStrategy {
#Override
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method, metadata, mappingContext);
return new PagingViewBasedCouchbaseQuery(queryMethod, couchbaseOperations);
}
}
private static class PagingViewBasedCouchbaseQuery extends ViewBasedCouchbaseQuery {
private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory
.getLogger(DCORepositoryFactory.PagingViewBasedCouchbaseQuery.class);
private CouchbaseOperations operations;
private CouchbaseQueryMethod method;
public PagingViewBasedCouchbaseQuery(CouchbaseQueryMethod method, CouchbaseOperations operations) {
super(method, operations);
this.operations = operations;
this.method = method;
}
/*
* (non-Javadoc)
*
* #see org.springframework.data.couchbase.repository.query.
* ViewBasedCouchbaseQuery#execute(java.lang.Object[]) added the ability
* to support paging
*/
#Override
public Object execute(Object[] runtimeParams) {
Query query = null;
Pageable pageable = null;
for (Object param : runtimeParams) {
if (param instanceof Query) {
query = (Query) param;
} else if (param instanceof Pageable) {
pageable = (Pageable) param;
} else {
throw new IllegalStateException(
"Unknown query param: (btw null is also not allowed and pagable cannot be null) " + param);
}
}
if (query == null) {
query = new Query();
}
query.setReduce(false);
if (pageable != null) {
CouchbaseClient client = operations.getCouchbaseClient();
View view = client.getView(designDocName(), viewName());
// Paginator p = new Paginator(client, view, query,
// pageable.getPageSize());
Paginator paginator = client.paginatedQuery(view, query, pageable.getPageSize());
// now we need to goto the start point
ViewResponse viewResponse = null;
// views are 0 base
int i = 0;
while (paginator.hasNext()) {
viewResponse = paginator.next();
if (pageable.getPageNumber() == i++) {
LOGGER.debug("Found the response for this page: {} ", i);
break;
}
}
if (viewResponse == null) {
LOGGER.debug("no view response so leaving now");
return null;
}
Class<?> type = method.getEntityInformation().getJavaType();
final List result = new ArrayList(viewResponse.size());
for (final ViewRow row : viewResponse) {
result.add(operations.findById(row.getId(), type));
}
return result;
} else {
return operations.findByView(designDocName(), viewName(), query, method.getEntityInformation()
.getJavaType());
}
}
/**
* Returns the best-guess design document name.
*
* #return the design document name.
*/
private String designDocName() {
if (method.hasViewAnnotation()) {
return method.getViewAnnotation().designDocument();
} else {
return StringUtils.uncapitalize(method.getEntityInformation().getJavaType().getSimpleName());
}
}
/**
* Returns the best-guess view name.
*
* #return the view name.
*/
private String viewName() {
if (method.hasViewAnnotation()) {
return method.getViewAnnotation().viewName();
} else {
return StringUtils.uncapitalize(method.getName().replaceFirst("find", ""));
}
}
}
#Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata repositoryMetadata) {
return DCORepository.class;
}
}

Java DAO classes for many-to-one relationship

I have a problem regarding how to save the objects in the Database in Java when having many-to-one relationship.
Basically I have 2 classes - UserVO and GroupVO, that look like this:
public class UserVO extends ValueObject implements Serializable {
/**
* The default serial version ID
*/
private static final long serialVersionUID = 1L;
private String login;
private String password;
private Long groupId;
public UserVO() {
super();
this.setLogin("");
this.setPassword("");
this.setGroupId(0L);
}
// all the getters and setters
// ...
}
and
public final class GroupVO extends ValueObject implements Serializable {
/**
* The default serial version ID
*/
private static final long serialVersionUID = 1L;
private String description;
private Set<UserVO> users = new HashSet<UserVO>();
public GroupVO() {
super();
this.setDescription("");
}
// all the getters and setters
// ...
}
Their super-class is a very simple abstract class:
public abstract class ValueObject {
private Long id;
private String name;
public ValueObject() {
super();
// the ID is auto-generated
// this.setId(0L);
this.setName("");
}
// all the getters and setters
// ...
}
Now I have to create the DAO classes for them. In the UserDAO I something like this for creating and inserting a user in the DB:
#Override
public Long create(UserVO user) throws IllegalArgumentException, DAOException {
if (user.getId() != null) {
throw new IllegalArgumentException("User may already be created, the user ID is not null.");
}
Object[] values = { user.getName(), user.getLogin(), user.getPassword(), user.getGroupId() };
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet generatedKeys = null;
try {
connection = daoFactory.getConnection();
preparedStatement = DAOUtil.prepareStatement(connection, SQL_CREATE_USER, true, values);
int affectedRows = preparedStatement.executeUpdate();
if (affectedRows == 0) {
throw new DAOException("Creating user failed, no rows affected.");
}
generatedKeys = preparedStatement.getGeneratedKeys();
if (generatedKeys.next()) {
user.setId(generatedKeys.getLong(1));
} else {
throw new DAOException("Creating user failed, no generated key obtained.");
}
} catch (SQLException e) {
throw new DAOException(e);
} finally {
DAOUtil.close(connection, preparedStatement, generatedKeys);
}
return user.getId();
}
There are also some helper Classes, but I guess you understand my code :).
And this is the GroupDAO create method:
#Override
public Long create(GroupVO group) throws IllegalArgumentException, DAOException {
if (group.getId() != null) {
throw new IllegalArgumentException("Group may already be created, the group ID is not null.");
}
Object[] values = { group.getName(), group.getDescription() };
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet generatedKeys = null;
try {
connection = daoFactory.getConnection();
preparedStatement = DAOUtil.prepareStatement(connection, SQL_CREATE_GROUP, true, values);
int affectedRows = preparedStatement.executeUpdate();
if (affectedRows == 0) {
throw new DAOException("Creating group failed, no rows affected.");
}
generatedKeys = preparedStatement.getGeneratedKeys();
if (generatedKeys.next()) {
group.setId(generatedKeys.getLong(1));
} else {
throw new DAOException("Creating group failed, no generated key obtained.");
}
} catch (SQLException e) {
throw new DAOException(e);
} finally {
DAOUtil.close(connection, preparedStatement, generatedKeys);
}
return group.getId();
}
Now, if I make a small test in the main function, for creating a group and saving in the DB, everything goes well:
DAOFactory usersGroupsRolesFactory = DAOFactory.getInstance("UsersGroupsRolesDB.jdbc");
System.out.println("DAOFactory successfully obtained: " + usersGroupsRolesFactory);
// Create an instance of the GroupDAO class
GroupDAO dao = usersGroupsRolesFactory.getGroupDAO();
// Create some GroupVO objects
GroupVO group1 = new GroupVO();
group1.setName("Administrators");
group1.setDescription("These users have all the right in the application");
dao.create(group1);
As GroupVO class has a set of UserVO objects, and in the main function if I also type:
UserVO user1 = new UserVO();
user1.setName("Palancica Pavel");
user1.setLogin("login_pavel");
user1.setPassword("password_pavel");
group1.getUsers().add(user1); // I may also add some more users
and say I am first time calling: dao.create(group1);
Normally, this shouldn't only save the Group info, but also all the associated UserVO objects.
For me that means that in the "create" function of the GroupDAO, after the group ID is successfully generated, I need to do a lot of other code.
I wonder is this is the correct way of saving those users in the DB, as I think I have to make the GroupDAO class to communicate with the UserDAO class, and also with the DAOFactory, which in my case, can give us an UserDAO, or GroupDAO object. Or I can do all the DB interection for saving those users without using the UserDAO class.
That code that I'm thinking seem very long, messy/spaghetti, and I am not quite sure if this is the correct approach :(.
Note that I am note using any ORM Framework.
Please let me know guys, what do you think about that?!
If you need more details, I can send you my Project, it's not commercial :D
Thanks in advance
I would use a GroupDAO to only create the group, a UserDAO to only create a user, and a functional service delegating to these two DAOs to create a group with all its users. Its code would look like the following:
Long groupId = groupDao.createGroup(groupVO);
for (UserVO userVO : groupVO.getUsers()) {
userDao.createUser(userVO, groupId);
}

ORMLite error no databasefield annotations exists

I have this error when I run my Android application:
No fields have a DatabaseField
annotation in class [[Lmodel.Vak;
My class Vak has annotations, so I really don't understand why it still giving me this error.
package model;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
#DatabaseTable(tableName = "vak")
public class Vak {
#DatabaseField(generatedId = true, columnName = "vakID", id=true) Long id;
#DatabaseField int rij;
#DatabaseField
int kolom;
...
}
I have a file called Databasehelper.java in which extends OrmLiteSqLiteOpenHelper and the file looks like this:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// name of the database file for your application -- change to something
// appropriate for your app
private static final String DATABASE_NAME = "project56.db";
// any time you make changes to your database objects, you may have to
// increase the database version
private static final int DATABASE_VERSION = 1;
private DatabaseType databaseType = new SqliteAndroidDatabaseType();
// the DAO object we use to access the tables
private Dao<Vleugel, Long> vleugelDao = null;
private Dao<Verdieping, Long> verdiepingDao = null;
private Dao<NavigatiePunt, Long> navigatiePuntDao = null;
private Dao<Lokaal, Long> lokaalDao = null;
private Dao<Raster, Long> rasterDao = null;
private Dao<Vak, Long> vakDao = null;
private Dao<Graaf, Long> graafDao = null;
private Dao<Vertex, Long> vertexDao = null;
private Dao<Edge, Long> edgeDao = null;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is first created. Usually you should
* call createTable statements here to create the tables that will store
* your data.
*/
#Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(DatabaseHelper.class.getName(), "onCreate");
TableUtils.createTable(connectionSource, Vleugel.class);
TableUtils.createTable(connectionSource, Verdieping.class);
TableUtils.createTable(connectionSource, NavigatiePunt.class);
TableUtils.createTable(connectionSource, Lokaal.class);
TableUtils.createTable(connectionSource, Raster.class);
TableUtils.createTable(connectionSource, Vak.class);
TableUtils.createTable(connectionSource, Graaf.class);
TableUtils.createTable(connectionSource, Vertex.class);
TableUtils.createTable(connectionSource, Edge.class);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
/**
* This is called when your application is upgraded and it has a higher
* version number. This allows you to adjust the various data to match the
* new version number.
*/
#Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource,
int oldVersion, int newVersion) {
try {
Log.i(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, Vleugel.class, true);
TableUtils.dropTable(connectionSource, Verdieping.class, true);
TableUtils.dropTable(connectionSource, NavigatiePunt.class, true);
TableUtils.dropTable(connectionSource, Lokaal.class, true);
TableUtils.dropTable(connectionSource, Raster.class, true);
TableUtils.dropTable(connectionSource, Vak.class, true);
TableUtils.dropTable(connectionSource, Graaf.class, true);
TableUtils.dropTable(connectionSource, Vertex.class, true);
TableUtils.dropTable(connectionSource, Edge.class, true);
// after we drop the old databases, we create the new ones
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Returns the Database Access Object (DAO) for the classes It will create
* it or just give the cached value.
*/
public Dao<Vleugel, Long> getVleugelDao() throws SQLException {
if (vleugelDao == null) {
vleugelDao = getDao(Vleugel.class);
}
return vleugelDao;
}
public Dao<Verdieping, Long> getVerdiepingDao() throws SQLException {
if (verdiepingDao == null) {
verdiepingDao = getDao(Verdieping.class);
}
return verdiepingDao;
}
public Dao<NavigatiePunt, Long> getNavigatiePuntDao() throws SQLException {
if (navigatiePuntDao == null) {
navigatiePuntDao = getDao(NavigatiePunt.class);
}
return navigatiePuntDao;
}
public Dao<Lokaal, Long> getLokaalDao() throws SQLException {
if (lokaalDao == null) {
lokaalDao = getDao(Lokaal.class);
}
return lokaalDao;
}
public Dao<Raster, Long> getRasterDao() throws SQLException {
if (rasterDao == null) {
rasterDao = getDao(Raster.class);
}
return rasterDao;
}
public Dao<Vak, Long> getVakDao() throws SQLException {
if (vakDao == null) {
vakDao = getDao(Vak.class);
}
return vakDao;
}
public Dao<Graaf, Long> getGraafDao() throws SQLException {
if (graafDao == null) {
graafDao = getDao(Graaf.class);
}
return graafDao;
}
public Dao<Vertex, Long> getVertexDao() throws SQLException {
if (vertexDao == null) {
vertexDao = getDao(Vertex.class);
}
return vertexDao;
}
public Dao<Edge, Long> getEdgeDao() throws SQLException {
if (edgeDao == null) {
edgeDao = getDao(Edge.class);
}
return edgeDao;
}
/**
* Close the database connections and clear any cached DAOs.
*/
#Override
public void close() {
super.close();
vleugelDao = null;
verdiepingDao = null;
navigatiePuntDao = null;
lokaalDao = null;
rasterDao = null;
vakDao = null;
graafDao = null;
vertexDao = null;
edgeDao = null;
}
}
I also have a file Controller which extends OrmLiteBaseActivity:
public class Controller extends OrmLiteBaseActivity<DatabaseHelper> {
Dao<Vleugel, Long> vleugelDao;
Dao<Verdieping, Long> verdiepingDao;
Dao<NavigatiePunt, Long> navigatiePuntDao;
Dao<Lokaal, Long> lokaalDao;
Dao<Raster, Long> rasterDao;
Dao<Graaf, Long> graafDao;
Dao<Vertex, Long> vertexDao;
Dao<Edge, Long> edgeDao;
Dao<Vak, Long> vakDao;
// Databasehelper is benodigd voor ORMLite
static {
OpenHelperManager.setOpenHelperFactory(new SqliteOpenHelperFactory() {
public OrmLiteSqliteOpenHelper getHelper(Context context) {
return new DatabaseHelper(context);
}
});
}
public Controller() throws SQLException {
/** initialiseren van dao */
vleugelDao = getHelper().getVleugelDao();
verdiepingDao = getHelper().getVerdiepingDao();
navigatiePuntDao = getHelper().getNavigatiePuntDao();
lokaalDao = getHelper().getLokaalDao();
rasterDao = getHelper().getRasterDao();
graafDao = getHelper().getGraafDao();
vertexDao = getHelper().getVertexDao();
edgeDao = getHelper().getEdgeDao();
vakDao = getHelper().getVakDao();
}
/**
* Haalt vleugel idNaam op uit dao object bijv. K1
*
* #return Vleugel
* #throws java.sql.SQLException
*/
public Vleugel getVleugel(String vleugelIDNaam)
throws java.sql.SQLException {
// select * from vleugel where idNaam='{vleugelIDNaam}'
QueryBuilder<Vleugel, Long> qb = vleugelDao.queryBuilder();
Where where = qb.where();
// the name field must be equal to "foo"
where.eq("idNaam", vleugelIDNaam);
PreparedQuery<Vleugel> preparedQuery = qb.prepare();
List<Vleugel> vleugelList = vleugelDao.query(preparedQuery);
Log.v("Getvleugel", vleugelList.size() + "");
if (vleugelList.size() == 1) {
return vleugelList.get(0);
}
return null;
}
public Verdieping getVerdieping(int nummer) throws java.sql.SQLException {
// TODO: Met querybuilder query naar db om verdieping te pakken
return null;
}
/**
* Haalt navigatiepunt op
*
* #param naam
* #return
* #throws java.sql.SQLException
*/
public NavigatiePunt getNavigatiePunt(String naam)
throws java.sql.SQLException {
// select * from navigatiepunt where naam='{naam}'
QueryBuilder<NavigatiePunt, Long> qb = navigatiePuntDao.queryBuilder();
Where where = qb.where();
where.eq("naam", naam);
PreparedQuery<NavigatiePunt> preparedQuery = qb.prepare();
List<NavigatiePunt> navigatieList = navigatiePuntDao
.query(preparedQuery);
Log.v("GetLokaal", navigatieList.size() + "");
if (navigatieList.size() == 1) {
return navigatieList.get(0);
}
return null;
}
/**
* Get lokaal object op basis van lokaalcode
*
* #param lokaalcode
* #return
* #throws java.sql.SQLException
*/
public Lokaal getLokaal(String lokaalcode) throws java.sql.SQLException {
// select * from lokaal where lokaalcode='{lokaalcode}'
QueryBuilder<Lokaal, Long> qb = lokaalDao.queryBuilder();
Where where = qb.where();
where.eq("lokaalcode", lokaalcode);
PreparedQuery<Lokaal> preparedQuery = qb.prepare();
List<Lokaal> lokaalList = lokaalDao.query(preparedQuery);
Log.v("GetLokaal", lokaalList.size() + "");
if (lokaalList.size() == 1) {
return lokaalList.get(0);
}
return null;
}
}
So do you have any advice on this, what should I check?
Could you check, are created table Vak in your DB? The absence of this table can be reason of this crash.
This turned out to be a bug in ORMLite around foreign object loops that was fixed in version 4.22. ORMLite was not properly handing the case where A has a foreign-field B which has a foreign-field to C which has a foreign-field back to A..
http://ormlite.com/releases/
Please send me some direct mail #Yanny if this does or doesn't work and I will tune this answer accordingly.
It's probably late for giving solution but this is my solution:
you see proguard try to obfuscating the code and if you read proguard in depth or intro
http://proguard.sourceforge.net/FAQ.html
what Shrinking in proguard -> Shrinking programs such as ProGuard can analyze bytecode and remove unused classes, fields, and methods.
so from this we can presume that it is removing your objects since it's not used by anywhere...
so wt you probably need?
you need to stop proguard from shirking that methods or objects from process
so this is the line for that..:
-keep class com.j256.**<br>
-keepclassmembers class com.j256.** { *; }<br>
-keep enum com.j256.**<br>
-keepclassmembers enum com.j256.** { *; }<br>
-keep interface com.j256.**<br>
-keepclassmembers interface com.j256.** { *; }
this line will keep proguard from removing my public methods and variables..
-keepclassmembers class classpath.** {
public *;
}
you need to write column name for atlest id... because it will search for it and will proguard change it's name... so you need to define column name id for primary key..

Categories