use of siena.SienaException in project siena by mandubian.
the class JdbcPersistenceManager method save.
@Override
public int save(Iterable<?> objects) {
Map<JdbcClassInfo, List<Object>> objMap = new HashMap<JdbcClassInfo, List<Object>>();
PreparedStatement ps = null;
for (Object obj : objects) {
JdbcClassInfo classInfo = JdbcClassInfo.getClassInfo(obj.getClass());
if (!objMap.containsKey(classInfo)) {
List<Object> l = new ArrayList<Object>();
l.add(obj);
objMap.put(classInfo, l);
} else {
objMap.get(classInfo).add(obj);
}
}
int total = 0;
try {
for (JdbcClassInfo classInfo : objMap.keySet()) {
if (!classInfo.generatedKeys.isEmpty()) {
ps = getConnection().prepareStatement(classInfo.insertOrUpdateSQL, Statement.RETURN_GENERATED_KEYS);
} else {
ps = getConnection().prepareStatement(classInfo.insertOrUpdateSQL);
}
for (Object obj : objMap.get(classInfo)) {
Field idField = classInfo.info.getIdField();
Object idVal = Util.readField(obj, idField);
// only generates a UUID if the idVal is null
if (idVal == null) {
for (Field field : classInfo.keys) {
Id id = field.getAnnotation(Id.class);
if (id.value() == Generator.UUID) {
field.set(obj, UUID.randomUUID().toString());
}
}
}
// TODO: implement primary key generation: SEQUENCE
int i = 1;
i = addParameters(obj, classInfo.allFields, ps, i);
addParameters(obj, classInfo.updateFields, ps, i);
ps.addBatch();
}
int[] res = ps.executeBatch();
if (!classInfo.generatedKeys.isEmpty()) {
ResultSet gk = ps.getGeneratedKeys();
int i;
int idx = 0;
int sz = objMap.get(classInfo).size();
// so we take only the first SZ values which are the key values.
while (gk.next() && idx < sz) {
i = 1;
for (Field field : classInfo.generatedKeys) {
field.setAccessible(true);
JdbcMappingUtils.setFromObject(objMap.get(classInfo).get(idx++), field, gk.getObject(i++));
}
}
}
total += res.length;
}
return total;
} catch (SienaException e) {
throw e;
} catch (Exception e) {
throw new SienaException(e);
} finally {
JdbcDBUtils.closeStatementAndConnection(this, ps);
}
}
use of siena.SienaException in project siena by mandubian.
the class GaeNativeSerializer method unembed.
public static <T> T unembed(Class<T> clazz, String embeddingFieldName, Entity entity, int level) {
// the level prevents from stackoverflow in case of a circular ref
if (level > 2)
return null;
if (clazz.isArray() || Collection.class.isAssignableFrom(clazz)) {
throw new SienaException("can't serializer Array/Collection in native mode");
}
T obj = Util.createObjectInstance(clazz);
try {
for (Field f : ClassInfo.getClassInfo(clazz).allFields) {
// doesn't try to analyze fields, just try to store it
String propName = embeddingFieldName + "." + ClassInfo.getSingleColumnName(f);
Object propValue = entity.getProperty(propName);
if (ClassInfo.isEmbedded(f) && f.getAnnotation(Embedded.class).mode() == Embedded.Mode.NATIVE) {
Object value = GaeNativeSerializer.unembed(f.getType(), embeddingFieldName + "." + ClassInfo.getSingleColumnName(f), entity, level + 1);
Util.setField(obj, f, value);
} else if (ClassInfo.isModel(f.getType())) {
// here we create a model with only the key as we don't embed anything else because there is no join by default
Class<?> fieldClass = f.getType();
Object value = Util.createObjectInstance(fieldClass);
Util.setField(value, ClassInfo.getIdField(fieldClass), propValue);
Util.setField(obj, f, value);
} else {
GaeMappingUtils.setFromObject(obj, f, propValue);
}
}
return obj;
} catch (Exception e) {
throw new SienaException(e);
}
}
use of siena.SienaException in project siena by mandubian.
the class GaePersistenceManagerAsync method mapJoins.
protected <T> List<T> mapJoins(QueryAsync<T> query, List<T> models) {
try {
// join queries
Map<Field, ArrayList<Key>> fieldMap = GaeQueryUtils.buildJoinFieldKeysMap(query);
// creates the list of joined entity keys to extract
for (final T model : models) {
for (Field field : fieldMap.keySet()) {
Object objVal = Util.readField(model, field);
// our object is not linked to another object...so it doesn't have any key
if (objVal == null) {
continue;
}
Key key = GaeMappingUtils.getKey(objVal);
List<Key> keys = fieldMap.get(field);
if (!keys.contains(key))
keys.add(key);
}
}
Map<Field, Map<Key, Entity>> entityMap = new HashMap<Field, Map<Key, Entity>>();
try {
// retrieves all joined entities per field
for (Field field : fieldMap.keySet()) {
Future<Map<Key, Entity>> entities = ds.get(fieldMap.get(field));
// gets the future here because we need it so we wait for it
entityMap.put(field, entities.get());
}
} catch (Exception ex) {
throw new SienaException(ex);
}
// associates linked models to their models
// linkedModels is just a map to contain entities already mapped
Map<Key, Object> linkedModels = new HashMap<Key, Object>();
Object linkedObj;
Entity entity;
for (final T model : models) {
for (Field field : fieldMap.keySet()) {
Object objVal = Util.readField(model, field);
// our object is not linked to another object...so it doesn't have any key
if (objVal == null) {
continue;
}
Key key = GaeMappingUtils.getKey(objVal);
linkedObj = linkedModels.get(key);
if (linkedObj == null) {
entity = entityMap.get(field).get(key);
linkedObj = objVal;
GaeMappingUtils.fillModel(linkedObj, entity);
linkedModels.put(key, linkedObj);
}
field.set(model, linkedObj);
}
}
return models;
} catch (IllegalAccessException ex) {
throw new SienaException(ex);
}
}
use of siena.SienaException in project siena by mandubian.
the class GaePersistenceManager method prepareKeysOnly.
private <T> PreparedQuery prepareKeysOnly(Query<T> query) {
Class<?> clazz = query.getQueriedClass();
ClassInfo info = ClassInfo.getClassInfo(clazz);
com.google.appengine.api.datastore.Query q;
// manages aggregation at first
List<QueryAggregated> aggregs = query.getAggregatees();
if (aggregs.isEmpty()) {
q = new com.google.appengine.api.datastore.Query(ClassInfo.getClassInfo(clazz).tableName);
} else if (aggregs.size() == 1) {
QueryAggregated aggreg = aggregs.get(0);
q = new com.google.appengine.api.datastore.Query(GaeMappingUtils.getKindWithAncestorField(info, ClassInfo.getClassInfo(aggreg.aggregator.getClass()), aggreg.field));
q.setAncestor(GaeMappingUtils.getKey(aggreg.aggregator));
} else {
throw new SienaException("Only one aggregation per query allowed");
}
return ds.prepare(GaeQueryUtils.addFiltersOrders(query, q).setKeysOnly());
}
use of siena.SienaException in project siena by mandubian.
the class GaeQueryUtils method nextPage.
public static <T> void nextPage(QueryData<T> query) {
QueryOptionPage pag = (QueryOptionPage) query.option(QueryOptionPage.ID);
QueryOptionState state = (QueryOptionState) query.option(QueryOptionState.ID);
QueryOptionGaeContext gaeCtx = (QueryOptionGaeContext) query.option(QueryOptionGaeContext.ID);
if (gaeCtx == null) {
gaeCtx = new QueryOptionGaeContext();
query.options().put(gaeCtx.type, gaeCtx);
}
// if no more data after, doesn't try to go after
if (gaeCtx.noMoreDataAfter) {
return;
}
// if no more data before, removes flag to be able and stay there
if (gaeCtx.noMoreDataBefore) {
gaeCtx.noMoreDataBefore = false;
return;
}
if (pag.isPaginating()) {
gaeCtx.realPageSize = pag.pageSize;
if (state.isStateless()) {
// QueryOptionOffset offset = (QueryOptionOffset)query.option(QueryOptionOffset.ID);
// if(offset.isActive()){
gaeCtx.realOffset += pag.pageSize;
// }
} else {
if (!gaeCtx.isActive()) {
QueryOptionOffset offset = (QueryOptionOffset) query.option(QueryOptionOffset.ID);
if (!gaeCtx.useCursor) {
// then uses offset (in case of IN or != operators)
// if(offset.isActive()){
gaeCtx.realOffset += pag.pageSize;
// }
} else // if the cursor is used, just passivates the offset
{
offset.passivate();
// keeps track of the offset anyway
gaeCtx.realOffset += pag.pageSize;
}
} else {
QueryOptionOffset offset = (QueryOptionOffset) query.option(QueryOptionOffset.ID);
// cursor added by a previousPage call which tries to go backward the first page
if (!gaeCtx.useCursor && !gaeCtx.hasNextCursor()) {
// then uses offset (in case of IN or != operators)
// if(offset.isActive()){
gaeCtx.realOffset += pag.pageSize;
// }
} else {
// forces cursor to be sure it is used
gaeCtx.useCursor = true;
String cursor = gaeCtx.nextCursor();
// if the cursor is null, it means we are back to the first page so we reactivate the offset
gaeCtx.realOffset += pag.pageSize;
if (cursor == null) {
offset.activate();
} else {
offset.passivate();
}
}
}
}
} else {
// throws exception because it's impossible to reuse nextPage when paginating has been interrupted, the cases are too many
throw new SienaException("Can't use nextPage after pagination has been interrupted...");
}
}
Aggregations