数据库封装
2016-04-18 19:02
411 查看
首先要感谢下面的这篇文章
http://blog.csdn.net/feiduclear_up/article/details/50557590
接下来贴上自己写好的代码
1.MyApplication.java
两个实体类如下
DBUtil .java 数据库工具类
DBHelper .java 创建数据库表
DBOperator .java 对数据库进行各种操作
http://blog.csdn.net/feiduclear_up/article/details/50557590
接下来贴上自己写好的代码
1.MyApplication.java
public class MyApplication extends Application { private DBOperator mDBOperator; private static MyApplication mApp; @Override public void onCreate() { super.onCreate(); mApp = this; } /** * 获取Application实例 * @return */ public static MyApplication getSelf(){ return mApp; } /** * 创建线程安全的数据库实例 * @return */ public synchronized DBOperator getDBOperator(){ if(mDBOperator == null){ mDBOperator = DBOperator.getInstance(this); } return mDBOperator; } }
两个实体类如下
public class Student { private String name; private String sex; private int age; public Student(){ } public Student(String name, int age, String sex) { this.name = name; this.age = age; this.sex = sex; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", age=" + age + '}'; } public String getName() { return name; } //注意:set和get方法必须提供,因为DBOperator的方法里面会通过反射获取 public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
public class Teacher { private String name; private int age; public Teacher(){ } public Teacher(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Teacher{" + "name='" + name + '\'' + ", age=" + age + '}'; } //注意:set和get方法必须提供,因为DBOperator的方法里面会通过反射获取 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
DBUtil .java 数据库工具类
public class DBUtil { /** * 获得表名 * @param clazz 实体类 * @return 表名 */ public static String getTableName(Class<?> clazz){ return clazz.getSimpleName().toLowerCase(); } /** * 获取表字段类型 * @param fileType 字段类型 * @return 数据库表字段类型 */ public static String getColumnType(String fileType){ String value = null; if (fileType.contains("String")) { value = " text";//注意:前面有个空格,目的是为了拼接 } else if (fileType.contains("int")) { value = " integer"; } else if (fileType.contains("boolean")) { value = " boolean "; } else if (fileType.contains("float")) { value = " float"; } else if (fileType.contains("double")) { value = " double"; } else if (fileType.contains("char")) { value = " varchar"; } else if (fileType.contains("long")) { value = " long"; } return value; } /** * 首字母大写 * @param string * @return */ public static String capitalize(String string) { if (!TextUtils.isEmpty(string)) { return string.substring(0, 1).toUpperCase(Locale.US) + string.substring(1); } return string == null ? null : ""; } }
DBHelper .java 创建数据库表
public class DBHelper extends SQLiteOpenHelper { private static final String TAG = "DBHelper"; private static final String DB_NAME = "person.db";//数据库名称 private static final int DB_VERSION = 1;//数据库版本,从1开始 public DBHelper(Context context) { super(context,DB_NAME,null,DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) {//数据库第一次创建执行,只执行一次,以后不再执行 Log.d(TAG, "onCreate: "); db.execSQL(getCreateTableSql(Student.class)); db.execSQL(getCreateTableSql(Teacher.class)); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {//只有当数据库版本号发生变化的时候才会执行 } /** * 获取创建表的语句 * @param clazz * @return */ private String getCreateTableSql(Class<?> clazz){ StringBuilder sb = new StringBuilder(); String tableName = DBUtil.getTableName(clazz); sb.append("create table "+tableName+" (ID INTEGER PRIMARY KEY AUTOINCREMENT,"); Field[] fields = clazz.getDeclaredFields();//通过反射获取所有字段 for (Field fd:fields){ String fieldName = fd.getName();//字段名 String fieldType = fd.getType().getName();//字段类型名 //不需要字段中的id,因为数据库表有自增id if(fieldName.equalsIgnoreCase("id")||fieldName.equalsIgnoreCase("_id")){ continue; }else{//拼接字段名和类型,例如 age int,name text, sb.append(fieldName).append(DBUtil.getColumnType(fieldType)).append(","); } } int length = sb.length(); sb.replace(length-1,length,")");//删除最后一个,age int,name text Log.d(TAG, "getCreateTableSql: "+sb.toString()); return sb.toString(); } }
DBOperator .java 对数据库进行各种操作
public class DBOperator { private static final String TAG = "DBOperator"; private static Context mContext; private SQLiteDatabase mDatabase; private DBOperator() { DBHelper dbHelper = new DBHelper(mContext); mDatabase = dbHelper.getReadableDatabase();//获取数据库对象 } //静态内部类实现单例 public static DBOperator getInstance(Context context) { mContext = context; return DBOperatorHolder.mOperator; } //静态内部类,创建单例对象 public static class DBOperatorHolder { private static final DBOperator mOperator = new DBOperator(); } /** * 关闭数据库 */ public void closeDatabase(){ mDatabase.close(); mDatabase = null; } /** * 删除数据库 * @param dataBaseName 数据库名称 */ public void deleteDatabase(String dataBaseName){ mContext.deleteDatabase(dataBaseName); } /** * 删除表 * @param clazz 表对应的实体类 */ public void deleteTable(Class<?> clazz){ mDatabase.execSQL("DROP TABLE IF EXISTS "+ clazz.getSimpleName()); } /** * 向指定的表中插入数据 * @param object 实体 * @param tableName 表名 * @return 插入行所在的id,如果返回-1,说明发生了错误 */ public long insert(Object object, String tableName) { ContentValues values = new ContentValues(); Cursor cursor = mDatabase.rawQuery("SELECT * FROM " + tableName, null); for (int i = 0; i < cursor.getColumnCount(); i++) { String name = cursor.getColumnName(i);//表中字段的名称 try { //去除从表中获取的id字段,因为实体类中没有此字段 if (!"id".equalsIgnoreCase(name) && !"_id".equalsIgnoreCase(name)) { Field field = object.getClass().getDeclaredField(name);//根据字段名称获取代表的Field对象 field.setAccessible(true);//让私有变量也可以访问 //当所有字段为String类型时可以用下面两行代码这种方式插入 // String value = (String) field.get(object); // values.put(name,value); putValues(values, field, object);//插入数据 } } catch (Exception e) { e.printStackTrace(); } } /** * 第一个参数 表名 * 第二个参数 nullColumnHack (作用)当values参数为空或者里面没有内容的时候,insert是会失败的(底层数据库不允许插入一个空行), * 为了防止这种情况,要在这里指定一个列名,到时候如果发现将要插入的行为空行时, * 就会将你指定的这个列名的值设为null,然后再向数据库中插入。 * 源码如下 * int size = (initialValues != null && initialValues.size() > 0) ? initialValues.size() : 0; if (size > 0) { bindArgs = new Object[size]; int i = 0; for (String colName : initialValues.keySet()) { sql.append((i > 0) ? "," : ""); sql.append(colName); bindArgs[i++] = initialValues.get(colName); } sql.append(')'); sql.append(" VALUES ("); for (i = 0; i < size; i++) { sql.append((i > 0) ? ",?" : "?"); } } else { sql.append(nullColumnHack + ") VALUES (NULL"); } */ return mDatabase.insert(tableName, null, values); } /** * 插入数据 * @param values 内容 * @param fd 字段对象 * @param obj 实体类 */ private void putValues(ContentValues values, Field fd, Object obj) { Class<?> clazz = values.getClass(); try { Object[] parameters = new Object[]{fd.getName(), fd.get(obj)};//创建包含字段名称和值的数组 Class<?>[] parameterTypes = getParameterTypes(fd, fd.get(obj), parameters); //根据方法名称和方法参数类型获得方法 Method method = clazz.getDeclaredMethod("put", parameterTypes); method.setAccessible(true); //调用方法,values调用方法的对象,parameters方法的参数 method.invoke(values, parameters); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } /** * 获取参数类型 * @param field 字段 * @param fieldValue 字段值, * @param parameters 保存字段名和字段值的数组 * @return 参数类型 */ private Class<?>[] getParameterTypes(Field field, Object fieldValue, Object[] parameters) { Class<?>[] parameterTypes; if (isCharType(field)) {//如果是字符类型,第二个参数当String处理 parameters[1] = String.valueOf(fieldValue); parameterTypes = new Class[]{String.class, String.class}; } else { //如果字段是基本数据类型,比如int,long,float,第二个参数为对应的class对象 if (field.getType().isPrimitive()) { parameterTypes = new Class[]{String.class, getObjectType(field.getType())}; //如果是Date类型,第二个参数为long类型 } else if ("java.util.Date".equals(field.getType().getName())) { parameterTypes = new Class[]{String.class, Long.class}; } else { parameterTypes = new Class[]{String.class, field.getType()}; } } return parameterTypes; } /** * 判断字段类型是否是字符 * @param field 字段 * @return true 是字符 */ private boolean isCharType(Field field) { //获得字段类型名称 String type = field.getType().getName(); return type.equals("char") || type.endsWith("Character"); } /** * 根据字段类型获取对象 * @param primitiveType * @return */ private Class<?> getObjectType(Class<?> primitiveType) { if (primitiveType != null) { if (primitiveType.isPrimitive()) { String basicTypeName = primitiveType.getName(); if ("int".equals(basicTypeName)) { return Integer.class; } else if ("short".equals(basicTypeName)) { return Short.class; } else if ("long".equals(basicTypeName)) { return Long.class; } else if ("float".equals(basicTypeName)) { return Float.class; } else if ("double".equals(basicTypeName)) { return Double.class; } else if ("boolean".equals(basicTypeName)) { return Boolean.class; } else if ("char".equals(basicTypeName)) { return Character.class; } } } return null; } /** * 查询所有数据 * @param clazz 实体类对象 * @param <T> 实体类 * @return 数据集合 */ public <T> List<T> findAll(Class<T> clazz) { //参数:表名, //columns,需要查询那些列,传入null会查询所有列的数据 //select 条件语句 //selectionargs 条件参数 //groupby 分组 //having //orderby Cursor cursor = mDatabase.query(clazz.getSimpleName(), null, null, null, null, null, null); return getEntity(cursor, clazz); } /** * 根据参数获取结果 * @param clazz 实体类对象 * @param select 条件语句 id = ? * @param selectArgs 条件参数 new String[]{"1"} * @param <T> 实体类 * @return */ public <T> List<T> findByArgs(Class<T> clazz,String select,String[] selectArgs){ Cursor cursor = mDatabase.query(clazz.getSimpleName(), null, select, selectArgs, null, null, null); return getEntity(cursor,clazz); } public <T> T findById(Class<T> clazz,int id){ Cursor cursor = mDatabase.query(clazz.getSimpleName(), null, "id=" + id, null, null, null, null); List<T> list = getEntity(cursor, clazz); android.util.Log.d(TAG, "findById: "+list); return list.get(0); } public int deleteById(Class<?> clazz,int id){ return mDatabase.delete(clazz.getSimpleName(),"id="+id,null); } public int deleteByArgs(Class<?> clazz,String select,String[] args){ return mDatabase.delete(clazz.getSimpleName(),select,args); } public int deleteAll(Class<?> clazz){ return mDatabase.delete(clazz.getSimpleName(),null,null); } public void updateById(Class<?> clazz,ContentValues values,int id){ mDatabase.update(clazz.getSimpleName(),values,"id="+id,null); } public <T> List<T> getEntity(Cursor cursor, Class<T> clazz) { List<T> list = new ArrayList<>(); try { if (cursor != null && cursor.moveToFirst()) { do { Field[] fields = clazz.getDeclaredFields(); T moduleClass = clazz.newInstance(); for (Field field : fields) { Class<?> cursorClass = cursor.getClass(); String columnMethodName = getColumnMethodName(field.getType()); Method cursorClassMethod = cursorClass.getMethod(columnMethodName, int.class); Object value = cursorClassMethod.invoke(cursor, cursor.getColumnIndex(field.getName())); if (field.getType() == boolean.class || field.getType() == Boolean.class) { if ("0".equals(String.valueOf(value))) { value = false; } else if ("1".equals(String.valueOf(value))) { value = true; } } else if (field.getType() == char.class || field.getType() == Character.class) { value = ((String) value).charAt(0); } else if (field.getType() == Date.class) { long date = (Long) value; if (date <= 0) { value = null; } else { value = new Date(date); } } String methodName = makeSetterMethodName(field); Method method = clazz.getDeclaredMethod(methodName, field.getType()); method.invoke(moduleClass, value); } list.add(moduleClass); } while (cursor.moveToNext()); } } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) { cursor.close(); } } return list; } private String getColumnMethodName(Class<?> fieldType) { String typeName; if (fieldType.isPrimitive()) {//如果此类代表的是基本数据类型 typeName = DBUtil.capitalize(fieldType.getName()); } else { typeName = fieldType.getSimpleName(); } String methodName = "get" + typeName; if ("getBoolean".equals(methodName)) { methodName = "getInt"; } else if ("getChar".equals(methodName) || "getCharacter".equals(methodName)) { methodName = "getString"; } else if ("getDate".equals(methodName)) { methodName = "getLong"; } else if ("getInteger".equals(methodName)) { methodName = "getInt"; } return methodName; } private String makeSetterMethodName(Field field) { String setterMethodName; String setterMethodPrefix = "set"; if (isPrimitiveBooleanType(field) && field.getName().matches("^is[A-Z]{1}.*$")) { setterMethodName = setterMethodPrefix + field.getName().substring(2); } else if (field.getName().matches("^[a-z]{1}[A-Z]{1}.*")) { setterMethodName = setterMethodPrefix + field.getName(); } else { setterMethodName = setterMethodPrefix + DBUtil.capitalize(field.getName()); } return setterMethodName; } private boolean isPrimitiveBooleanType(Field field) { Class<?> fieldType = field.getType(); if ("boolean".equals(fieldType.getName())) { return true; } return false; } }
相关文章推荐
- Navicat for oracle 提示 cannot load OCI DLL,126 193的解决方法
- Oracle笔记(十六) 数据库设计范式
- Oracle笔记(十五) 数据库备份
- Oracle笔记(十四) 用户管理
- Oracle笔记(十三) 视图、同义词、索引
- Result consisted of more than one row
- Oracle笔记(十二) 集合、序列
- 初时mysql
- Oracle笔记(十一) 建表、更新、查询综合练习
- Oracle to_date/Trunc函数用法及date字段只精确到日期的问题
- Oracle笔记(十) 约束
- Oracle笔记(九) 表的创建及管理
- Oracle笔记(八) 复杂查询及总结
- Oracle笔记(七) 数据更新、事务处理、数据伪列
- Oracle笔记(六) 多表查询
- mysql+C#实战三:数据库查询操作;
- Redis命令-有序集合-zrank
- WampServer修改Mysql密码的步骤
- Oracle触发器表发生了变化 触发器不能读它解决方法
- mysql-explain