knu project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

211 lines
7.5 KiB

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package kr.co.kihyun.spring;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import javax.jdo.PersistenceManagerFactory;
import kr.co.kihyun.beans.entity.AssignType;
import kr.co.kihyun.beans.entity.MoumiEntity;
import kr.co.kihyun.beans.entity.TotDoc;
import kr.co.kihyun.beans.entity.util.PMF;
import kr.co.kihyun.moumi.MoumiConfig;
import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.OMFContext;
import org.datanucleus.jdo.JDOPersistenceManagerFactory;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.MetaDataManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
*
* @author bhs
*/
public class MoumiJdbcDao<T extends MoumiEntity> extends JdbcDaoSupport implements MoumiDao<T> {
private static Logger LOG = LoggerFactory.getLogger(MoumiJdbcDao.class);
private AbstractClassMetaData metaData;
private Set<String> dirtyFields = new HashSet<String>(2);
private MetaDataManager metaDataManager;
private ClassLoaderResolver classLoaderResolver;
public AbstractClassMetaData getMetaData() {
return metaData;
}
public Set<String> getDirtyFields() {
return Collections.unmodifiableSet(dirtyFields);
}
public void addDirtyField(String field) {
this.dirtyFields.add(field);
}
private Properties getPmfProperties() {
Properties result = new Properties();
InputStream stream = MoumiConfig.class.getResourceAsStream("/moumi-pmf.properties");
try {
result.load(stream);
return result;
} catch (IOException e) {
throw new RuntimeException("unable to read moumi-pmf.properties file.");
}
}
private void init(Class<T> c, PersistenceManagerFactory pmf) {
OMFContext omfContext = new JDOPersistenceManagerFactory(pmf.getProperties()).getOMFContext();
this.metaDataManager = omfContext.getMetaDataManager();
this.classLoaderResolver = omfContext.getClassLoaderResolver(null);
this.metaData = metaDataManager.getMetaDataForClass((Class<T>) c, classLoaderResolver);
}
private class MoumiRowMapper implements ParameterizedRowMapper<T> {
private Class clazz;
public <T extends MoumiEntity<Object>> MoumiRowMapper(Class<T> c) {
this.clazz = c;
}
public T mapRow(ResultSet rs, int rownum) throws SQLException {
T pc = null;
try {
pc = (T) clazz.newInstance();
} catch (Exception ex) {
throw new RuntimeException("Could not instantiate class " + clazz.getSimpleName());
}
int skipCount = 0;
pc.setId(rs.getObject(1));
for (AbstractMemberMetaData member : MoumiJdbcDao.this.metaData.getManagedMembers()) {
Field field = null;
Object fieldValue = null;
try {
if (member.isRelationOwner(classLoaderResolver)) {
field = clazz.getDeclaredField(member.getMemberRepresented().getName());
field.setAccessible(true);
fieldValue = rs.getObject(member.getAbsoluteFieldNumber() - skipCount);
if (field.getType().isEnum()) {
int ordinal = ((Integer) fieldValue).intValue();
Object[] values = (Object[]) field.getType().getMethod("values").invoke(fieldValue);
field.set(pc, field.getType().cast(values[ordinal]));
} else if (MoumiEntity.class.isInstance(field.getType().newInstance())) {
MoumiEntity e = (MoumiEntity) field.getType().newInstance();
e.setId((Long) fieldValue);
TotDoc doc = (TotDoc) field.getType().cast(e);
field.set(pc, field.getType().cast(e));
} else {
field.set(pc, field.getType().cast(fieldValue));
}
} else {
skipCount++;
}
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException(this.clazz.getSimpleName()
+ " is incompatible type or unwrapping conversion fails."
+ " field: " + member.getMemberRepresented().getName()
+ " field number: " + member.getAbsoluteFieldNumber()
+ " field value: " + fieldValue);
} catch (IllegalAccessException ex) {
throw new RuntimeException(member.getMemberRepresented().getName()
+ " field is set to be acceessable but could not access to this field.", ex);
} catch (NoSuchFieldException ex) {
throw new RuntimeException(member.getMemberRepresented().getName()
+ " is present at metadata but could not be found at class."
+ " It seems to be not enhanced.", ex);
} catch (ClassCastException cce) {
// throw new ClassCastException(cce.getMessage() + ": field '" + field.getName() + "'");
LOG.warn("{}: field '{}'", cce.getMessage(), field.getName());
} catch (Exception ex) {
// throw new RuntimeException("Could not map row for field "
// + member.getMemberRepresented().getName(), ex);
LOG.warn("Could not map row for field '{}'", member.getMemberRepresented().getName());
}
}
return pc;
}
}
public MoumiJdbcDao(Class<T> c) {
Properties props = getPmfProperties();
init(c, new JDOPersistenceManagerFactory(props));
}
public MoumiJdbcDao(Class<T> c, PersistenceManagerFactory pmf) {
init(c, pmf);
}
public T load(Class<T> c, Long id) {
// TODO Apply fetch plan.
return (T) this.getJdbcTemplate().queryForObject("select * from " + this.metaData.getTable() + " where id = ?",
// return (T) this.getJdbcTemplate().queryForObject("select id from " + this.metaData.getTable() + " where id = ?",
new Object[]{id}, new MoumiRowMapper(c));
}
public void store(Class<T> c, T pc) {
if (dirtyFields.isEmpty())
return;
List<Object> params = new ArrayList<Object>();
StringBuilder sql = new StringBuilder(100);
sql.append("update ").append(this.metaData.getTable()).append(" set ");
int i = 0;
for (Iterator<String> iter = dirtyFields.iterator(); iter.hasNext(); i++) {
String dirtyField = iter.next();
if (this.metaData.getMetaDataForMember(dirtyField).getColumnMetaData()[0].getName() != null) {
sql.append(this.metaData.getMetaDataForMember(dirtyField).getColumnMetaData()[0].getName());
} else {
sql.append(dirtyField);
}
sql.append(" = ?");
try {
Field field = c.getDeclaredField(dirtyField);
field.setAccessible(true);
if (field.get(pc) instanceof Enum) {
params.add(((Enum) field.get(pc)).ordinal());
} else {
params.add(field.get(pc));
}
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException(ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (NoSuchFieldException ex) {
throw new RuntimeException("Field " + dirtyField + " does not exists in class "
+ c.getSimpleName() + ". "
+ "Check addDirtyField(String field) method invocations.");
} catch (SecurityException ex) {
throw new SecurityException(ex);
}
if (i != dirtyFields.size() - 1) {
sql.append(", ");
}
}
sql.append(" where id = ?");
params.add(pc.getId());
LOG.debug(sql.toString().replaceAll("\\?", "{}"), params.toArray(new Object[params.size()]));
this.getJdbcTemplate().update(sql.toString(), params.toArray(new Object[params.size()]));
}
}