package com.jqmobile.core.server.db.orm;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.jqmobile.core.orm.TableUtil;
import com.jqmobile.core.orm.exception.ORMException;
import com.jqmobile.core.orm.exception.ORMParamNotRecognitionException;
import com.jqmobile.core.utils.plain.FieldType;
import com.jqmobile.core.utils.plain.GUIDUtils;
import com.jqmobile.core.utils.plain.ModBean;
import com.jqmobile.core.utils.plain.ModColumn;
import com.jqmobile.core.utils.plain.UUIDUtils;
class ModORMImpl implements ModORM {
private ModBean initModiBean;
// 数据库连接对象
private Connection connection = null;
private List<ModColumn> modiColumns=null;
/**
* 初始化
*
* @param conn
*/
public ModORMImpl(Connection conn,ModBean modiBean) {
this.initModiBean=modiBean;
this.modiColumns=modiBean.getModiColumns();
this.connection = conn;
}
/**
* 自动验证表
*
* @throws ORMException
*/
private boolean autoValiTable(String tableName) {
TableUtil tableUtil = TableUtilFactory.instance(connection);
try {
return tableUtil.valiTableExist(tableName);
} catch (ORMException e) {
e.printStackTrace();
}
return false;
}
/*
* (non-Javadoc)
*
* @see com.jiuqi.mobile.orm.base.ORMModi#insert(T)
*/
@Override
public int insert(ModBean modiBean) throws ORMException {
int row = 0;
if (autoValiTable(modiBean.getTableName())) {
try {
String sql = insertSql(modiBean);
PreparedStatement ps = connection.prepareStatement(sql);
setValue(ps,modiBean,sql);
try {
row = ps.executeUpdate();
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
} else {
throw new ORMException("表不存在");
}
return row;
}
/**
* INT,SHORT,LONG,DOUBLE,FLOAT,STRING,UUID,GUID,DATE
* @param ps
* @param modiBean
* @throws SQLException
* @throws ORMException
*/
private void setValue(PreparedStatement ps, ModBean modiBean,String sql) throws SQLException, ORMException {
List<ModColumn> mcs = modiBean.getModiColumns();
int j=1;
for (int i=1;i<mcs.size()+1;i++) {
ModColumn mc=mcs.get(i-1);
if(mc.getType()!=null){
if(mc.getType().toString().equals("INT")){
ps.setInt(j, (Integer) mc.getValue());
j++;
continue;
}else if(mc.getType().toString().equals("SHORT")){
ps.setShort(j, (Short) mc.getValue());
j++;
continue;
}else if(mc.getType().toString().equals("DOUBLE")){
ps.setBigDecimal(j, new BigDecimal((Double) mc.getValue()));
j++;
continue;
}else if(mc.getType().toString().equals("FLOAT")){
ps.setFloat(j, (Float) mc.getValue());
j++;
continue;
}else if(mc.getType().toString().equals("STRING")){
if(mc.isPaimaryId()&&!sql.contains("insert")){
ps.setBytes(mcs.size(), UUIDUtils.getBytes(mc.getValue()));
continue;
}else if(mc.isPaimaryId()&&sql.contains("insert")){
ps.setBytes(j, UUIDUtils.getBytes(mc.getValue()));
j++;
continue;
}else{
ps.setString(j, (String) mc.getValue());
j++;
continue;
}
}else if(mc.getType().toString().equals("UUID")){
if(mc.isPaimaryId()&&!sql.startsWith("insert")){
ps.setBytes(mcs.size(), UUIDUtils.getBytes(mc.getValue()));
continue;
}else{
j++;
ps.setBytes(mcs.size()+1, UUIDUtils.getBytes(mc.getValue()));
continue;
}
}else if(mc.getType().toString().equals("DATE")){
Timestamp ts=new Timestamp((Long) mc.getValue());
ps.setTimestamp(j, ts);
j++;
continue;
}else if(mc.getType().toString().equals("LONG")){
ps.setLong(j, (Long) mc.getValue());
j++;
continue;
}else{
throw new ORMException("类型映射错误,不支持此类型");
}
}else{
throw new ORMException("列类型为null");
}
}
}
/**
* 拼装insert语句 insert into user ( id ,name,pwd) values(4,'d','d');
*
* @param modiBean
* @return
*/
private String insertSql(ModBean modiBean) {
StringBuilder sb = new StringBuilder(" insert into "
+ modiBean.getTableName() + " ( ");
List<ModColumn> mcs = modiBean.getModiColumns();
for (ModColumn mc : mcs) {
sb.append(mc.getName() + ", ");
}
sb.deleteCharAt(sb.length() - 2);
sb.append(" ) values(");
for (int i=0;i<mcs.size();i++) {
sb.append(" ?, ");
}
String sql=sb.substring(0, sb.toString().length()-2)+" ); ";
return sql;
}
/*
* @see com.jiuqi.mobile.orm.base.ORMModi#update(T)
*/
@Override
public int update(ModBean modiBean) throws ORMException {
if (autoValiTable(modiBean.getTableName())) {
try {
String sql = updateSql(modiBean);
PreparedStatement ps = connection.prepareStatement(sql);
setValue(ps, modiBean,sql);
try {
return ps.executeUpdate();
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
} else {
throw new ORMException("表不存在");
}
}
/**
* 更新语句 update user set name='sssss' where id=1
*
* @param modiBean
* @return
*/
private String updateSql(ModBean modiBean) {
StringBuilder sb = new StringBuilder(" update "
+ modiBean.getTableName() + " set ");
List<ModColumn> mcs = modiBean.getModiColumns();
for (ModColumn mc : mcs) {
if (mc.isPaimaryId()) {
continue;
}
sb.append(mc.getName() + " = " +"?,");
}
sb.delete(sb.length()-1, sb.length());
for (ModColumn mc : mcs) {
if (mc.isPaimaryId()) {
sb.append(" where "+ mc.getName()+ " =?");
}
}
return sb.toString();
}
@Override
public int delete(ModBean modiBean) throws ORMException {
if (autoValiTable(modiBean.getTableName())) {
try {
String sql = deleteSql(modiBean);
PreparedStatement ps = connection.prepareStatement(sql);
setValue(ps, modiBean, sql);
try {
return ps.executeUpdate();
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
} else {
throw new ORMException("表不存在");
}
}
/**
* 删除sql delete from user where id=4
*
* @param modiBean
* @return
*/
private String deleteSql(ModBean modiBean) {
StringBuilder sb = new StringBuilder(" delete from "
+ modiBean.getTableName() + " where ");
List<ModColumn> mcs = modiBean.getModiColumns();
for (ModColumn mc : mcs) {
if (mc.isPaimaryId()) {
sb.append(mc.getName()+"=?");
break;
}
}
return sb.toString();
}
@Override
public ModBean find(String tableName, String recid, String paimaryId)
throws ORMException {
return find(tableName, UUID.fromString(recid), paimaryId);
}
/**
* @throws ORMException
* @see com.jiuqi.mobile.orm.base.ORMModi#find(java.lang.String,
* java.util.UUID, java.lang.String)
*/
@Override
public ModBean find(String tableName, UUID recid, String paimaryId) {
if (autoValiTable(tableName)) {
String sql = findByIdSql(tableName, recid, paimaryId);
try {
return query(sql,null).get(0);
} catch (ORMException e) {
e.printStackTrace();
}
} else {
try {
throw new ORMException("表不存在");
} catch (ORMException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 单条查询
*
* @param tableName
* @param recid
* @param paimaryId
* @return
*/
private String findByIdSql(String tableName, UUID recid, String paimaryId) {
StringBuilder sb = new StringBuilder(" select * from " + tableName
+ " where ");
sb.append(paimaryId + " = " + GUIDUtils.getBytes(recid));
return sb.toString();
}
/**
* @see com.jiuqi.mobile.orm.base.ORMModi#getAll()
*/
@Override
public List<ModBean> getAll(String tableName) throws ORMException {
String sql = "select * from " + tableName;
return query(sql);
}
@Override
public List<ModBean> query(String sql, Object... args) throws ORMException {
try {
PreparedStatement ps = connection.prepareStatement(sql);
if(args!=null&&args.length>0){
setValue(ps, args);
}
try {
ResultSet rs = ps.executeQuery();
try {
return getList(rs);
} catch (Exception e) {
throw new ORMException(e);
} finally {
rs.close();
}
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
}
private void setValue(PreparedStatement ps, Object[] args) throws SQLException {
for(int i=0;i<args.length;i++){
Object obj=args[i];
if(obj instanceof UUID){
ps.setObject(i+1, UUIDUtils.getBytes(obj));
}else if(obj.getClass().isPrimitive()){
ps.setObject(i+1, obj);
}else if(obj instanceof byte[] || obj instanceof Byte[]){
ps.setObject(i+1, obj);
}else{
throw new ORMParamNotRecognitionException(obj);
}
}
}
private List<ModBean> getList(ResultSet rs) throws SQLException,
ClassNotFoundException, ORMException {
ResultSetMetaData rsmd = rs.getMetaData();
List<ModBean> list = new ArrayList<ModBean>();
while (rs.next()) {
ModBean modiBean = new ModBean();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
ModColumn mc = new ModColumn();
mc.setName(rsmd.getColumnName(i + 1));
FieldType type=getFieldType(rsmd.getColumnTypeName(i + 1));
mc.setType(type);
mc.setValue(rs.getObject(i + 1));
modiBean.addColumn(mc);
}
list.add(modiBean);
}
return list;
}
/**
* bigint
* @param columnTypeName
* @return
* @throws ORMException
*/
private FieldType getFieldType(String columnTypeName) throws ORMException {
if(columnTypeName.toLowerCase().equals("binary")){
return FieldType.BYTEARRAY;
}else if(columnTypeName.toLowerCase().equals("smallint")){
return FieldType.SHORT;
}else if(columnTypeName.toLowerCase().equals("int")){
return FieldType.INT;
}else if(columnTypeName.toLowerCase().equals("float")){
return FieldType.FLOAT;
}else if(columnTypeName.toLowerCase().equals("decimal")){
return FieldType.DOUBLE;
}else if(columnTypeName.toLowerCase().equals("varchar")||columnTypeName.toLowerCase().equals("char")){
return FieldType.STRING;
}else if(columnTypeName.toLowerCase().equals("timestamp")){
return FieldType.DATE;
}else if(columnTypeName.toLowerCase().equals("bigint")){
return FieldType.INT;
}else{
throw new ORMException("类型映射错误,不支持此类型");
}
}
@Override
public List<ModBean> queryPage(String sql, long startIndex, long endIndex,
Object... args) throws ORMException {
try {
sql = sql + " limit ?,?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setLong(args.length + 1, startIndex);
ps.setLong(args.length + 2, endIndex);
try {
ResultSet rs = ps.executeQuery();
try {
return getList(rs);
} catch (Exception e) {
throw new ORMException(e);
} finally {
rs.close();
}
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
}
@Override
public ModBean queryFirst(String sql, Object... args) throws ORMException {
return query(sql, args).get(0);
}
@Override
public int queryRow(String sql, Object... args) throws ORMException {
try {
PreparedStatement ps = connection.prepareStatement(sql);
if (args != null && args.length > 0) {
setValue(ps, args);
}
try {
ResultSet rs = ps.executeQuery();
try {
if (rs.next())
return rs.getInt(1);
return 0;
} catch (Exception e) {
throw new ORMException(e);
} finally {
rs.close();
}
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
}
@Override
public int update(String sql, Object... args) throws ORMException {
try {
PreparedStatement ps = connection.prepareStatement(sql);
if (args != null && args.length > 0) {
setValue(ps, args);
}
try {
return ps.executeUpdate();
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
}
@Override
public int delete(String sql, Object... args) throws ORMException {
try {
PreparedStatement ps = connection.prepareStatement(sql);
if (args != null && args.length > 0) {
setValue(ps, args);
}
try {
return ps.executeUpdate();
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
}
@Override
public int delete(String recid) throws ORMException {
return delete(UUID.fromString(recid));
}
@Override
public int delete(UUID recid) throws ORMException {
for(ModColumn mc:modiColumns){
if(mc.isPaimaryId()){
mc.setValue(recid);
}
}
return delete(initModiBean);
}
@Override
public ModBean find(String recid) {
return find(recid);
}
@Override
public ModBean find(UUID recid) {
String paimaryName="";
for(ModColumn mc:modiColumns){
if(mc.isPaimaryId()){
paimaryName=mc.getName();
}
}
return find(initModiBean.getTableName(),recid,paimaryName);
}
@Override
public List<ModBean> getAll() throws ORMException {
return getAll(initModiBean.getTableName());
}
@Deprecated
/**
* 不可用
*/
public <D> List<D> queryRaw(String sql, Object[] args, ICallBack<D> back)
throws SQLException, InstantiationException, IllegalAccessException {
return null;
}
@Deprecated
/**
* 不可用
*/
public <D> List<D> queryRaw(String sql, long startIndex, long endIndex,
Object[] args, ICallBack<D> iCallBack) throws SQLException,
InstantiationException, IllegalAccessException {
return null;
}
@Deprecated
/**
* 不可用
*/
public <D> D queryRawFirst(String sql, Object[] args, ICallBack<D> back)
throws SQLException, InstantiationException, IllegalAccessException {
return null;
}
@Deprecated
/**
* 不可用
*/
public int modifyRaw(String sql, Object... args) throws SQLException {
return 0;
}
@Deprecated
/**
* 不可用
*/
public int deleteRaw(String sql, Object... args) throws SQLException {
return 0;
}
@Deprecated
/**
* 不可用
*/
public PreparedStatement getPrepareStatement(String sql)
throws SQLException {
return null;
}
@Override
public void createTable() throws ORMException {
if (autoValiTable(initModiBean.getTableName())) {
try {
String sql = creatTableSql();
System.out.println(sql);
PreparedStatement ps = connection.prepareStatement(sql);
try {
ps.executeUpdate();
} finally {
ps.close();
}
} catch (SQLException e) {
throw new ORMException(e);
}
}else{
try {
throw new ORMException("表不存在");
} catch (ORMException e) {
e.printStackTrace();
}
}
}
/**
* CREATE TABLE `t_datetest` (
* `id` binary(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
* `birthday` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
* PRIMARY KEY (`id`)
* )
* @param modiBean
* @return
* @throws ORMException
*/
private String creatTableSql() throws ORMException {
StringBuilder sb = new StringBuilder("create table `"
+ initModiBean.getTableName() + "` ( ");
String id="";
for (ModColumn mc : modiColumns) {
sb.append("`"+mc.getName() + "` "+getDataBaseType(mc));
if(mc.isPaimaryId()){
id=mc.getName();
}
}
sb.append(" PRIMARY KEY (`"+id+"`) \n)");
return sb.toString();
}
private String getDataBaseType(ModColumn modiColumn) throws ORMException {
String type=modiColumn.getType().toString().toUpperCase();
if(type.equals("LONG")){
return "bigint(20)"+",";
}else if(type.equals("DOUBLE")){
return "decimal(17,5)"+",";
}else if(type.equals("INT")){
return "int"+",";
}else if(type.equals("Float")){
return "float"+",";
}else if(type.equals("DATE")){
return "timestamp"+",";
}else if(type.equals("SHORT")){
return "smallint"+",";
}else if(type.equals("STRING")){
if(modiColumn.isPaimaryId()){
return "bigint(20)"+",";
}
return "varchar"+",";
}else{
throw new ORMException("类型映射错误,不支持此类型");
}
}
}