суббота, 9 апреля 2011 г.

Simple ORM

Наверное многие начинающие java программисты задумывались над тем, как неудобно писать слой взаимодейстия с базой данных на чистом JDBC. Ctrl+c, Ctrl+v и изменение названия таблиц и параметров. Все это приводит к излишнему дублированию кода. Конечно можно сразу взять тот же Hibernate или любую другую реализацию JPA. Но для небольших и простых проектов, имхо это как "из пушки по воробьям". К тому же считаю что надо один раз написать ORM самому, чтобы понять основы его работы.

В этой статье рассмотрим создание своего простого ORM на примере работы с СУБД Oracle.

Создадим интерфейс Persistence и реализующий его класс PersistenceOraImpl - собственно сам персистенс Api для работы с БД.

Список методов в Persistence:

1. selectAll - выбирает все записи из таблицы;
2. select - выбирает записи по заданным параметрам;
3. selectRow - выбирает одну запись по заданным параметрам;
4. insert - вставляет запись;
5. update - обновляет запись;
6. delete - удаляет запись.

Сам интерфейс выглядит так:
public interface Persistence {

 public List selectAll(Class<?> clazz);

 public List select(Class<?> clazz, Map<String, Object> params);

 public Object selectRow(Class<?> clazz, Map<String, Object> params);

 public void insert(Object obj);

 public void update(Object obj);

 public void delete(Class<?> clazz, Map<String, Object> params);

 public Connection getConnection();

 public void setConnection(Connection conn);
}



Имплементим методы в классе PersistenceOraImpl.

selectAll:
@Override
@Override
public List selectAll(Class<?> clazz) {

 try {

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    "select t.* from " + PersistenceHelper.defineTable(clazz) + " t");

  OracleResultSet orset = (OracleResultSet) stmt.executeQuery();
  List treeList = new ArrayList();

  while (orset.next()) {

   Constructor constructor = clazz.getConstructor(null);
   Object somethingInstance = constructor.newInstance(null);
   Field[] fields = clazz.getDeclaredFields();

   Map<Integer, Class<?>> mapFields = PersistenceHelper.defineFields(clazz);

   /*выполняем методы set...()*/
   for (Integer i = 1; i <= mapFields.size(); i++) {
    String s = fields[i - 1].getName();
    s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

    Method method = clazz.getMethod("set" + s, mapFields.get(i));
    method.invoke(somethingInstance, PersistenceHelper.getSqlValue(orset, mapFields.get(i), i));
   }

   treeList.add(somethingInstance);
  }
  orset.close();
  stmt.close();

  return treeList;

 } catch (Exception ex) {
  ex.printStackTrace();
  return nullArray;
 }
}
select:
@Override
public List select(Class<?> clazz, Map<String, Object> params) {
 try {

  String sSql = "select t.* from " + PersistenceHelper.defineTable(clazz) + " t ";
  String sSql1 = "where ";

  Integer j = 1;
  for (String key : params.keySet()) {
   if (key.equals("period")) {
    sSql1 += " to_char(t.period,'MM.yyyy') = to_char(?,'MM.yyyy') ";
   } else if (key.substring(key.length() - 1).equals(">")) {
    sSql1 += key + "= ?";
   } else if (key.substring(key.length() - 1).equals("<")) {
    sSql1 += key + "= ?";
   } else {
    sSql1 += key + " = ?";
   }

   if (j++ < params.size()) {
    sSql1 += " and ";
   }
  }

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1);

  System.out.println("select: " + sSql + sSql1);

  j = 1;
  for (String key : params.keySet()) {
   PersistenceHelper.setSqlValue(stmt, params.get(key).getClass(), j++, params.get(key));
  }

  OracleResultSet orset = (OracleResultSet) stmt.executeQuery();
  List treeList = new ArrayList();

  while (orset.next()) {

   Constructor constructor = clazz.getConstructor(null);
   Object somethingInstance = constructor.newInstance(null);
   Field[] fields = clazz.getDeclaredFields();

   Map<Integer, Class<?>> mapFields = PersistenceHelper.defineFields(clazz);

   /*выполняем методы set...()*/
   for (Integer i = 1; i <= mapFields.size(); i++) {
    String s = fields[i - 1].getName();
    s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

    Method method = clazz.getMethod("set" + s, mapFields.get(i));
    method.invoke(somethingInstance, PersistenceHelper.getSqlValue(orset, mapFields.get(i), i));
   }

   treeList.add(somethingInstance);
  }
  orset.close();
  stmt.close();

  return treeList;

 } catch (Exception ex) {
  ex.printStackTrace();
  return nullArray;
 }
}
selectRow:
@Override
public Object selectRow(Class<?> clazz, Map<String, Object> params) {

 try {

  String sSql = "select t.* from " + PersistenceHelper.defineTable(clazz) + " t ";
  String sSql1 = " where ";

  Integer j = 1;
  for (String key : params.keySet()) {
   if (key.equals("period")) {
    sSql1 += " to_char(t.period,'MM') = to_char(?,'MM') ";
   } else {
    sSql1 += key + " = ? ";
   }

   if (j++ < params.size()) {
    sSql1 += " and ";
   }
  }

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1);

  System.out.println("selectRow: " + sSql + sSql1);
  j = 1;
  for (String key : params.keySet()) {
   PersistenceHelper.setSqlValue(stmt, params.get(key).getClass(), j++, params.get(key));
  }

  OracleResultSet orset = (OracleResultSet) stmt.executeQuery();
  List treeList = new ArrayList();

  while (orset.next()) {
   Constructor constructor = clazz.getConstructor(null);
   Object somethingInstance = constructor.newInstance(null);
   Field[] fields = clazz.getDeclaredFields();

   Map<Integer, Class<?>> mapFields = PersistenceHelper.defineFields(clazz);

   /*выполняем методы set...()*/
   for (Integer i = 1; i <= mapFields.size(); i++) {
    String s = fields[i - 1].getName();
    s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

    Method method = clazz.getMethod("set" + s, mapFields.get(i));
    method.invoke(somethingInstance, PersistenceHelper.getSqlValue(orset, mapFields.get(i), i));
   }

   treeList.add(somethingInstance);
  }

  orset.close();
  stmt.close();

  if (treeList.size() > 0) {
   return treeList.get(0);
  } else {
   Constructor constructor = clazz.getConstructor(null);
   return constructor.newInstance(null);
  }

 } catch (Exception ex) {
  ex.printStackTrace();
  return new Object();
 }
}
insert:
@Override
public void insert(Object obj) {

 try {

  Class<?> clazz = obj.getClass();

  Map<Integer, Class<?>> mapFields = PersistenceHelper.defineFields(clazz);
  Map<Integer, String> mapFieldNames = PersistenceHelper.defineFieldNames(clazz);
  Field[] fields = clazz.getDeclaredFields();

  String sSql = "insert into " + PersistenceHelper.defineTable(clazz) + " t ";
  String sSql1 = "(";
  String sSql2 = ") values (";

  for (int i = 1; i <= mapFieldNames.size(); i++) {
   if (i < mapFieldNames.size()) {
    sSql1 += mapFieldNames.get(i) + ",";
    sSql2 += "?,";
   } else {
    sSql1 += mapFieldNames.get(i);
    sSql2 += "?";
   }
  }

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1 + sSql2 + ")");

  /*выполняем методы get...()*/
  for (Integer i = 1; i <= mapFields.size(); i++) {
   String s = fields[i - 1].getName();
   s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

   Method method = clazz.getMethod("get" + s);
   Object o = method.invoke(obj);
   PersistenceHelper.setSqlValue(stmt, mapFields.get(i), i, o);
  }

  stmt.executeUpdate();

  stmt.close();

 } catch (Exception ex) {
  ex.printStackTrace();
 }

}
update:
@Override
public void update(Object obj) {

 try {

  Class<?> clazz = obj.getClass();

  Map<Integer, Class<?>> mapFields = PersistenceHelper.defineFields(clazz);
  Map<Integer, String> mapFieldNames = PersistenceHelper.defineFieldNames(clazz);
  Field[] fields = clazz.getDeclaredFields();

  String sSql = "update " + PersistenceHelper.defineTable(clazz) + " t set ";
  String sSql1 = "";

  for (int i = 1; i <= mapFieldNames.size(); i++) {
   if (i < mapFieldNames.size()) {
    sSql1 += mapFieldNames.get(i) + " = ? , ";
   } else {
    sSql1 += mapFieldNames.get(i) + " = ? ";
   }
  }

  /*привяжем условие по первому полю. обычно это id*/
  sSql1 += " where " + mapFieldNames.get(1) + " = ?";

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1);

  /*выполняем методы get...()*/
  for (Integer i = 1; i <= mapFields.size(); i++) {
   String s = fields[i - 1].getName();
   s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());


   Method method = clazz.getMethod("get" + s);
   Object o = method.invoke(obj);

   PersistenceHelper.setSqlValue(stmt, mapFields.get(i), i, o);

   /*привяжем переменную where*/
   if (i == 1) {
    PersistenceHelper.setSqlValue(stmt, mapFields.get(i), mapFields.size() + 1, o);
   }
  }


  stmt.executeUpdate();
  stmt.close();

 } catch (Exception ex) {
  ex.printStackTrace();
 }
}
delete:
@Override
public void delete(Class<?> clazz, Map<String, Object> params) {
 try {

  String sSql = "delete from " + PersistenceHelper.defineTable(clazz) + " t ";
  String sSql1 = " where ";

  Integer j = 1;
  for (String key : params.keySet()) {
   if (key.equals("period")) {
    sSql1 += " to_char(t.period,'MM') = to_char(?,'MM') ";
   } else {
    sSql1 += key + " = ? ";
   }

   if (j++ < params.size()) {
    sSql1 += " and ";
   }
  }

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1);

  j = 1;
  for (String key : params.keySet()) {
   PersistenceHelper.setSqlValue(stmt, params.get(key).getClass(), j++, params.get(key));
  }

  stmt.executeUpdate();
  stmt.close();

 } catch (Exception ex) {
  ex.printStackTrace();
 }
}
Остальная часть класса:
public class PersistenceOraImpl implements Persistence {

 private static final List nullArray = new ArrayList();

 private OracleConnection conn;

 public PersistenceOraImpl(OracleConnection conn) {
  setConnection(conn);
 }
 
 /* методы CRUD 
  ...
 */
 
 @Override
 public OracleConnection getConnection() {
  return conn;
 }

 @Override
 public void setConnection(Connection conn) {
  this.conn = (OracleConnection) conn;
 }
 
В методах используется вспомогательный класс PersistenceHelper:
public class PersistenceHelper {


 /**
  * Возвращает название таблицы из аннотации
  *
  * @param clazz тип передаваемого класса
  * @return oracle String.
  */
 public static String defineTable(Class clazz) {
  String table;

  if (clazz.isAnnotationPresent(OraDataTable.class)) {
   table = clazz.getAnnotation(OraDataTable.class).value();
  } else {
   throw new IllegalStateException(clazz.getName() + " must be @OraDataTable");
  }
  return table.toUpperCase();
 }

 /**
  * Возвращает названия и типы полей
  *
  * @param clazz тип передаваемого класса
  * @return oracle Map.
  */
 public static Map<Integer, Class<?>> defineFields(Class<?> clazz) {
  Map<Integer, Class<?>> map = new HashMap<Integer, Class<?>>();

  Field[] fields = clazz.getDeclaredFields();
  for (Field field : fields) {
   if (field.isAnnotationPresent(OraInteger.class)) {
    map.put(field.getAnnotation(OraInteger.class).value(), Integer.class);
   } else if (field.isAnnotationPresent(OraString.class)) {
    map.put(field.getAnnotation(OraString.class).value(), String.class);
   } else if (field.isAnnotationPresent(OraDate.class)) {
    map.put(field.getAnnotation(OraDate.class).value(), Date.class);
   } else if (field.isAnnotationPresent(OraTimestamp.class)) {
    map.put(field.getAnnotation(OraTimestamp.class).value(), Timestamp.class);
   } else if (field.isAnnotationPresent(OraBigDecimal.class)) {
    map.put(field.getAnnotation(OraBigDecimal.class).value(), BigDecimal.class);
   } else if (field.isAnnotationPresent(OraClob.class)) {
    map.put(field.getAnnotation(OraClob.class).value(), Clob.class);
   } else if (field.isAnnotationPresent(OraBlob.class)) {
    map.put(field.getAnnotation(OraBlob.class).value(), Blob.class);
   }
  }

  return map;
 }

 public static Map<Integer, String> defineFieldNames(Class<?> clazz) {
  Map<Integer, String> map = new HashMap<Integer, String>();

  Field[] fields = clazz.getDeclaredFields();
  for (Field field : fields) {
   if (field.isAnnotationPresent(OraInteger.class)) {
    map.put(field.getAnnotation(OraInteger.class).value(),
      field.getAnnotation(OraInteger.class).field());
   } else if (field.isAnnotationPresent(OraString.class)) {
    map.put(field.getAnnotation(OraString.class).value(),
      field.getAnnotation(OraString.class).field());
   } else if (field.isAnnotationPresent(OraDate.class)) {
    map.put(field.getAnnotation(OraDate.class).value(),
      field.getAnnotation(OraDate.class).field());
   } else if (field.isAnnotationPresent(OraTimestamp.class)) {
    map.put(field.getAnnotation(OraTimestamp.class).value(),
      field.getAnnotation(OraTimestamp.class).field());
   } else if (field.isAnnotationPresent(OraBigDecimal.class)) {
    map.put(field.getAnnotation(OraBigDecimal.class).value(),
      field.getAnnotation(OraBigDecimal.class).field());
   } else if (field.isAnnotationPresent(OraClob.class)) {
    map.put(field.getAnnotation(OraClob.class).value(),
      field.getAnnotation(OraClob.class).field());
   } else if (field.isAnnotationPresent(OraBlob.class)) {
    map.put(field.getAnnotation(OraBlob.class).value(),
      field.getAnnotation(OraBlob.class).field());
   }
  }

  return map;
 }

 public static Object getSqlValue(OracleResultSet orset, Class<?> oraType, Integer i) throws SQLException {
  if (oraType.getName().equals("java.lang.Integer")) {
   return orset.getInt(i);
  } else if (oraType.getName().equals("java.lang.String")) {
   return orset.getString(i);
  } else if (oraType.getName().equals("java.sql.Date")) {
   return orset.getDate(i);
  } else if (oraType.getName().equals("java.sql.Timestamp")) {
   return orset.getTimestamp(i);
  } else if (oraType.getName().equals("java.math.BigDecimal")) {
   return orset.getBigDecimal(i);
  } else if (oraType.getName().equals("java.sql.Clob")) {
   return orset.getClob(i);
  } else if (oraType.getName().equals("java.sql.Blob")) {
   return orset.getBlob(i);
  } else {
   return null;
  }
 }

 public static void setSqlValue(OraclePreparedStatement stmt, Class<?> oraType, Integer i, Object val) throws SQLException, Exception {
  if (oraType.getName().equals("java.lang.Integer")) {
   stmt.setInt(i, (Integer) (val == null ? 0 : val));
  } else if (oraType.getName().equals("java.lang.String")) {
   stmt.setString(i, (String) val);
  } else if (oraType.getName().equals("java.sql.Date")) {
   stmt.setDate(i, (Date) val);
  } else if (oraType.getName().equals("java.sql.Timestamp")) {
   stmt.setTimestamp(i, (Timestamp) val);
  } else if (oraType.getName().equals("java.math.BigDecimal")) {
   stmt.setBigDecimal(i, (BigDecimal) val);
  } else if (oraType.getName().equals("java.sql.Clob")) {
   stmt.setClob(i, (Clob) val);
  } else if (oraType.getName().equals("java.sql.Blob")) {
   stmt.setBlob(i, (Blob) val);
  } else {
   throw new Exception("error in setSqlValue. Unknown type: " + oraType.getName());
  }
 }

 public static void setStatementValue(OracleCallableStatement ocs, String key, Class<?> oraType, Integer i, Object val) throws SQLException, Exception {
  if (key.equals("out")) {
   if (oraType.getName().equals("java.lang.Integer")) {
    ocs.registerOutParameter(1, OracleTypes.INTEGER);
   } else if (oraType.getName().equals("java.lang.String")) {
    ocs.registerOutParameter(1, OracleTypes.VARCHAR);
   } else if (oraType.getName().equals("java.sql.Date")) {
    ocs.registerOutParameter(1, OracleTypes.DATE);
   } else if (oraType.getName().equals("java.sql.Timestamp")) {
    ocs.registerOutParameter(1, OracleTypes.TIMESTAMP);
   } else if (oraType.getName().equals("java.math.BigDecimal")) {
    ocs.registerOutParameter(1, OracleTypes.NUMBER);
   } else if (oraType.getName().equals("java.sql.Clob")) {
    ocs.registerOutParameter(1, OracleTypes.CLOB);
   } else if (oraType.getName().equals("java.sql.Blob")) {
    ocs.registerOutParameter(1, OracleTypes.BLOB);
   } else if (oraType.getName().equals("java.sql.Array")) {
    ocs.registerOutParameter(1, OracleTypes.ARRAY);
   } else {
    throw new Exception("error in setStatementValue. Unknown out type: " + oraType.getName());
   }
  } else {
   if (oraType.getName().equals("java.lang.Integer")) {
    ocs.setInt(i, (Integer) val);
   } else if (oraType.getName().equals("java.lang.String")) {
    ocs.setString(i, (String) val);
   } else if (oraType.getName().equals("java.sql.Date")) {
    ocs.setDate(i, (Date) val);
   } else if (oraType.getName().equals("java.sql.Timestamp")) {
    ocs.setTimestamp(i, (Timestamp) val);
   } else if (oraType.getName().equals("java.math.BigDecimal")) {
    ocs.setBigDecimal(i, (BigDecimal) val);
   } else if (oraType.getName().equals("java.sql.Clob")) {
    ocs.setClob(i, (Clob) val);
   } else if (oraType.getName().equals("java.sql.Blob")) {
    ocs.setBlob(i, (Blob) val);
   } else if (oraType.getName().equals("java.sql.Array")) {
    ocs.setArray(i, (Array) val);
   } else {
    throw new Exception("error in setStatementValue. Unknown type: " + oraType.getName());
   }
  }
 }

 public static Object getStatementValue(OracleCallableStatement ocs, Class<?> oraType, Integer i) throws SQLException, Exception {
  if (oraType.getName().equals("java.lang.Integer")) {
   return ocs.getInt(1);
  } else if (oraType.getName().equals("java.lang.String")) {
   return ocs.getString(i);
  } else if (oraType.getName().equals("java.util.Date")) {
   return ocs.getDate(1);
  } else if (oraType.getName().equals("java.sql.Timestamp")) {
   return ocs.getTimestamp(1);
  } else if (oraType.getName().equals("java.math.BigDecimal")) {
   return ocs.getBigDecimal(1);
  } else if (oraType.getName().equals("java.sql.Clob")) {
   return ocs.getClob(1);
  } else if (oraType.getName().equals("java.sql.Blob")) {
   return ocs.getBlob(1);
  } else if (oraType.getName().equals("java.sql.Array")) {
   return ocs.getArray(1);
  } else {
   throw new Exception("error in setStatementValue. Unknown out type: " + oraType.getName());
  }
 }
}
Аннотации для обработки entity с помощью reflection:
/**
 * Аннотация класса.
 */
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraDataTable {
 /**
  * @return oracle table.
  */
 String value();
}

/**
 * Аннотация аттрибута класса.
 * для конвертации oracle.sql.Int в объект Integer.
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraInteger {
 /**
  * @return oracle Integer.
  */
 int value();

 String field();

}

/**
 * Аннотация аттрибута класса.
 * для конвертации oracle.sql.String в объект String.
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraString {
 /**
  * @return oracle String.
  */
 int value();

 String field();

}

/**
 * Аннотация аттрибута класса.
 * для конвертации oracle.sql.Int в объект Integer.
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraBigDecimal {
 /**
  * @return oracle Integer.
  */
 int value();

 String field();
}

/**
 * Аннотация аттрибута класса.
 * для конвертации oracle.sql.Int в объект Integer.
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraDate {
 /**
  * @return oracle Integer.
  */
 int value();

 String field();
}
С другими типами аннотации аналогичны. Теперь с помощью созданных аннотаций можно создать обьект-сущность. Из определения ORM (Object-relational mapping) следует что это отображение Java-обьектов в реляционный вид.
/**
 *  Обьект-сущность
 */
@OraDataTable("my_table")
public class MyTable {

 @OraInteger(value = 1, field = "id")
 private Integer id;

 @OraString(value = 2, field = "name")
 private Integer periodType;
 
 /* и т.д. */
 
 public String getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
 
 /* и т.д. */

}
после этого можно проводить операции с этой сущностью в базе данных:
/*достанем все записи из таблицы my_table*/
public List<MyTable> getAllRecords() {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();  
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
  
  List<MyTable> resultList = persistence.selectAll(CalcPeriod.class);
  
  conn.close();
  return resultList;
 } catch (SQLException e) {
  e.printStackTrace();
  return nullArray;
 }
}

/*достанем несколько записей из таблицы my_table по условию*/
public List<MyTable> getListRecords(MyTable entity) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
  
  Map<String, Object> params = new HashMap<String, Object>();
  if (entity.getId() != null) params.put("id", entity.getId());
  
  List<MyTable> resultList = persistence.select(entity.getClass(), params);
  
  conn.close();
  return resultList;
 } catch (SQLException e) {
  e.printStackTrace();
  return nullArray;
 }
}

/*достанем одну запись из таблицы my_table по условию*/
public MyTable getRecordById(Integer inId) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
  
  Map<String, Object> params = new HashMap<String, Object>();
  if (inId != null) params.put("id", inId);
  
  MyTable result = (MyTable) persistence.selectRow(MyTable.class, params);
  
  conn.close();
  return result;
 } catch (SQLException e) {
  e.printStackTrace();
  return null;
 }
}

/*создадим запись в таблице my_table*/
public void insertRecord(MyTable entity) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
     
  persistence.insert(entity);
  
  conn.close();
 } catch (SQLException e) {
  e.printStackTrace();
 }
}

/*обновим запись в таблице my_table*/
public void updateRecord(MyTable entity) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
     
  persistence.update(entity);
  
  conn.close();
 } catch (SQLException e) {
  e.printStackTrace();
 }
}

/*удалим запись в таблице my_table*/
public void deleteRecord(MyTable entity) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
     
  Map<String, Object> params = new HashMap<String, Object>();
  if (entity.getId() != null) params.put("id", entity.getId());

  persistence.delete(entity.getClass(), params);
  
  conn.close();
 } catch (SQLException e) {
  e.printStackTrace();
 }
}
Замечу что в данном примере я беру connection к БД из готового dataSource.

Конечно данный ORM покажется излишне простым, нельзя работать с join-ами, транзакции придется писать самому и еще нельзя много чего другого. Думаю в нашем случае это и не надо.
Ну и напоследок стоит упомянуть, что серьезные ORM, например Hibernate, написаны с использованием FastMethod из cglib, и тем самым работают на порядок быстрее, чем с использованием reflection.

Комментариев нет:

Отправить комментарий