文档章节

通用数据库CRUD操作

chenruibing
 chenruibing
发布于 2015/05/29 23:56
字数 2226
阅读 480
收藏 0
点赞 0
评论 0

对于属性  id  表单名的注解

package com.example.dbcommon.dao.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 指定了实体的字段与数据库中表中列的对应关系
 * @author Administrator
 *
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
	/**
	 * 数据库中的表名
	 * @return
	 */
	String value();
}
package com.example.dbcommon.dao.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 标志主键
 * @author Administrator
 *
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ID {

	boolean autoincrement();
	
}
package com.example.dbcommon.dao.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 制定了将实体与数据库表中的对应关系
 * @author Administrator
 *
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
	/**
	 * 数据库中的表名
	 * @return
	 */
	String value();
}
实体类。可以直接在实体类注解,这样就知道了类的属性对应表的那个字段以及是否是id并且是否自增长等
package com.example.dbcommon.dao.domain;

import com.example.dbcommon.dao.DBHelper;
import com.example.dbcommon.dao.annotation.Column;
import com.example.dbcommon.dao.annotation.ID;
import com.example.dbcommon.dao.annotation.TableName;

@TableName(DBHelper.TABLE_NEWS_NAME)
public class News {

	//主键:明确,值的获取
	@ID(autoincrement=true)
	@Column(DBHelper.TABLE_ID)
	private int id;
	@Column(DBHelper.TABLE_NEWS_TITLE)
	private String title;
	@Column(DBHelper.TABLE_NEW_SUMMARY)
	private String summary;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getSummary() {
		return summary;
	}
	public void setSummary(String summary) {
		this.summary = summary;
	}
	
}
CRUD操作通用接口
package com.example.dbcommon.dao;

import java.io.Serializable;
import java.util.List;

/**
 * 实体操作的通用接口
 * @author Administrator
 *
 */
public interface DAO<M> {
	
	long insert(M m);
	int delete(Serializable id); //int long String
	int update(M m);
	List<M> findAll();
}

继承接口实现通用操作(基于所有类)

cursor.close()不关的话,最多提供300多个游标,超过了不报错,但是游标是空的,即便查出数据了也是空的

可以获取当前运行的类

通过class可以获取支持泛型的父类,也可以获取父类泛型的类型

通过class可以获取注解的value值,也可以设置value的值

通过class可以遍历所有字段

//问题1:表名的获取
    //解决方案1:获取到实体,字母小写就是表名。。不过定义实体的名称被受限制
    //解决方案2:利用注解,实体名称和数据库表名称脱离关系

package com.example.dbcommon.dao;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import com.example.dbcommon.dao.annotation.Column;
import com.example.dbcommon.dao.annotation.ID;
import com.example.dbcommon.dao.annotation.TableName;

import android.R.id;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.Data;
import android.util.Log;

public abstract class DaoSupportt<M> implements DAO<M>{


	private static final String TAG = "DaoSupportt";
	protected Context context;
	protected DBHelper helper;
	protected SQLiteDatabase db;
	public DaoSupportt(Context context) {
		super();
		this.context = context;
		this.helper = new DBHelper(context);
		this.db = helper.getWritableDatabase();
	}
	@Override
	public long insert(M m) {
		// TODO Auto-generated method stub
		ContentValues values = new ContentValues();
		
		fillColumn(m,values);//数据源第一个参数,导入的目标第二个参数
		return db.insert(getTableName(), null, values);
	}
	
	@Override
	public int delete(Serializable id) {
		// TODO Auto-generated method stub
		return db.delete(getTableName(), DBHelper.TABLE_ID + " =?", new String[]{id.toString()});
	}
	@Override
	public int update(M m) {
		// TODO Auto-generated method stub
		ContentValues values = new ContentValues();
		
		fillColumn(m,values);//数据源第一个参数,导入的目标第二个参数
		return db.update(getTableName(), values, DBHelper.TABLE_ID + " =?	", new String[]{getid(m)});
	}
	
	public List<M> findByCondition(String[] columns, String selection,
            String[] selectionArgs, String orderBy){
		return findByCondition(columns, selection, selectionArgs, null, null, orderBy);
	}
	
	/**
	 * 条件查询
	 * @param columns
	 * @param selection
	 * @param selectionArgs
	 * @param groupBy
	 * @param having
	 * @param orderBy
	 * @return
	 */
	public List<M> findByCondition(String[] columns, String selection,
            String[] selectionArgs, String groupBy, String having,
            String orderBy){
		List<M> result = null;
		Cursor cursor = db.query(getTableName(), columns, selection, selectionArgs, groupBy,
                having, orderBy);
		if(cursor != null){
			result = new ArrayList<M>();
			while(cursor.moveToNext()){
				M m = getInstrance();
				
				fillField(cursor,m);
				
				result.add(m);
			}
			//不关的话,最多提供300多个游标,超过了也不报错,但是提供的游标是空的,即便查出数据了也是空的
			cursor.close();
		}
		return result;
	}
	
	@Override
	public List<M> findAll() {
		// TODO Auto-generated method stub
		List<M> result = null;
		Cursor cursor = db.query(getTableName(), null, null, null, null, null, null);
		if(cursor != null){
			result = new ArrayList<M>();
			while(cursor.moveToNext()){
				M m = getInstrance();
				
				fillField(cursor,m);
				
				result.add(m);
			}
			//不关的话,最多提供300多个游标,超过了也不报错,但是提供的游标是空的,即便查出数据了也是空的
			cursor.close();
		}
		return result;
	}
	
	
	//问题1:表名的获取
	//解决方案1:获取到实体,字母小写就是表名。。不过定义实体的名称被受限制
	//解决方案2:利用注解,实体名称和数据库表名称脱离关系
	private String getTableName(){
		
		//获取实体
		M m = getInstrance();
		//获取实体的注解,依据value里设置值确定操作的数据库表
		//如果需要在运行时获取到注解的信息,设置存活的时间
		TableName tableName = m.getClass().getAnnotation(TableName.class);//annotationType:注解的类型
		if(tableName != null){
			return tableName.value();
		}
		return "";
	}
	//问题5:实体的对象创建
	private M getInstrance(){
		//实体是何时确定的?
		
		//1:是那个孩子调用的该方法-那个孩子在运行
		//jdk解释:返回此Object的运行时类
		Class clazz = getClass();
		//class com.ithm.dbhm28.dao.impl.NewsDaoImpl
//		Log.i(TAG, clazz.toString());
		
		//2:获取该孩子的父类(支持泛型的父类)
//		clazz.getSuperclass();//class com.ithm.dbhm28.dao.base.DAOSupport
		Type superclass = clazz.getGenericSuperclass();//com.ithm.dbhm28.dao.base.DAOSupport<com.ithm.dbhm28.dao.domain.News>
		//泛型实现接口,只要是泛型都会实现这个接口(参数化的类型),规定了泛型的通用操作
		if(superclass != null && superclass instanceof ParameterizedType){
			//[class com.ithm.dbhm28.dao.domain.News]
			Type[] arguments = ((ParameterizedType)superclass).getActualTypeArguments();
			try {
				return (M) ((Class)arguments[0]).newInstance();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		//3:获取到泛型中的参数
		return null;
	}
	//问题2:如何将实体中的数据,按照对应关系导入到数据库表中
	private void fillColumn(M m, ContentValues values) {
		// TODO Auto-generated method stub
//		values.put(DBHelper.TABLE_NEWS_TITLE, news.getTitle());
//		//此处省略N行代码
//		m.getClass().getFields();//获取类的所有public字段
		Field[] fields = m.getClass().getDeclaredFields();//获取类的所有字段
		for(Field item : fields){
			//要有权限 要不然一定会进入IllegalArgumentException这报没有权限的异常
			item.setAccessible(true);
			Column column = item.getAnnotation(Column.class);
			if(column != null){
				String key = column.value();
				
				try {
					String value = item.get(m).toString();
					//如果该field是主键,并且是自增的,不能添加到集合中
					ID id = item.getAnnotation(ID.class);
					if(id!=null && id.autoincrement()){
						//是主键就不要给数据,一旦给予数据,数据库就认为程序猿自己接管主键数据,数据库不再自增添加
					}else{
						values.put(key, value);
					}
					
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}
	}
	//问题4:明确实体中主键,获取到主键中封装的值
	private String getid(M m) {
		// TODO Auto-generated method stub
		Field[] fields = m.getClass().getDeclaredFields();
		for(Field item : fields){
			item.setAccessible(true);
			ID id = item.getAnnotation(ID.class);
			if(id != null){
				try {
					return item.get(m).toString();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return null;
	}
	
	//问题3:将数据表中列的数据,按照对应关系导入到实体中
	private void fillField(Cursor cursor, M m) {
		// TODO Auto-generated method stub

//		int columnIndex = cursor.getColumnIndex(DBHelper.TABLE_NEWS_TITLE);
//		String title = cursor.getString(columnIndex);
//		news.setTitle(title);
//		此处省略N行代码
		
		Field[] fields = m.getClass().getDeclaredFields();
		for(Field item : fields){
			item.setAccessible(true);
			Column column = item.getAnnotation(Column.class);
			if(column != null){
				int columnIndex = cursor.getColumnIndex(column.value());
				String value = cursor.getString(columnIndex);
				//在News里面  id是int类型   在这里是String类型,所以填充数据会出错
				try {
					if(item.getType() == int.class){
						item.set(m, Integer.parseInt(value));
					}else if(item.getType() == Data.class){
						//字符串转换成时间
					}else{
						item.set(m, value);
					}
					
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
接口类实现特定的类的通用CRUD接口,接口约束规范化
package com.example.dbcommon.dao;

import java.util.List;

import com.example.dbcommon.dao.domain.News;

/**
 * 新闻表操作的接口
 * @author Administrator
 *
 */
public interface NewsDao extends DAO<News>{

//	long insert(News news);
//	int delete(int id);
//	int update(News news);
//	List<News> findAll();
}

具体类实现特定的类的CRUD接口

package com.example.dbcommon.dao.impl;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.example.dbcommon.dao.DBHelper;
import com.example.dbcommon.dao.DaoSupportt;
import com.example.dbcommon.dao.NewsDao;
import com.example.dbcommon.dao.domain.News;

public class NewsDaoImpl extends DaoSupportt<News> implements NewsDao {

	public NewsDaoImpl(Context context) {
		super(context);
		
	}
	
	/*@Override
	public long insert(News news) {
		// TODO Auto-generated method stub
		ContentValues values = new ContentValues();
		values.put(DBHelper.TABLE_NEWS_TITLE, news.getTitle());
		//此处省略N行代码
		return db.insert(DBHelper.TABLE_NEWS_NAME, null, values);
	}
	

	@Override
	public int delete(int id) {
		// TODO Auto-generated method stub
		return db.delete(DBHelper.TABLE_NEWS_NAME, DBHelper.TABLE_ID + " =?", new String[]{id+""});
	}

	@Override
	public int update(News news) {
		// TODO Auto-generated method stub
		ContentValues values = new ContentValues();
		values.put(DBHelper.TABLE_NEWS_TITLE, news.getTitle());
		//此处省略N行代码
		return db.update(DBHelper.TABLE_NEWS_NAME, values, DBHelper.TABLE_ID + " =?	", new String[]{news.getId() + ""});
	}

	@Override
	public List<News> findAll() {
		// TODO Auto-generated method stub
		List<News> result = null;
		Cursor cursor = db.query(DBHelper.TABLE_NEWS_NAME, null, null, null, null, null, null);
		if(cursor != null){
			result = new ArrayList<News>();
			while(cursor.moveToNext()){
				News news = new News();
				int columnIndex = cursor.getColumnIndex(DBHelper.TABLE_NEWS_TITLE);
				String title = cursor.getString(columnIndex);
				news.setTitle(title);
				//此处省略N行代码
				result.add(news);
			}
			//不关的话,最多提供300多个游标,超过了也不报错,但是提供的游标是空的,即便查出数据了也是空的
			cursor.close();
		}
		return null;
	}*/

}

进行测试

package com.example.dbcommon.test;

import java.util.List;

import com.example.dbcommon.dao.DBHelper;
import com.example.dbcommon.dao.domain.News;
import com.example.dbcommon.dao.impl.NewsDaoImpl;

import android.test.AndroidTestCase;

public class DBTest extends AndroidTestCase {

	public void createTable(){
		DBHelper hbHelper = new DBHelper(getContext());
		hbHelper.getWritableDatabase();
	}
	
	public void testInsert(){
		NewsDaoImpl impl = new NewsDaoImpl(getContext());
		News m = new News();
		m.setTitle("测试标题一");
		m.setSummary("测试摘要一");
		impl.insert(m);
	}

	public void testDelete(){
		NewsDaoImpl impl = new NewsDaoImpl(getContext());
		impl.delete(0);
	}
	public void testUpdate(){
		NewsDaoImpl impl = new NewsDaoImpl(getContext());
		News m = new News();
		m.setId(2);
		m.setTitle("hm28N");
		m.setSummary("PP");
		impl.update(m);
	}
	public void testFindAll(){
		NewsDaoImpl impl = new NewsDaoImpl(getContext());
		List<News> findAll = impl.findAll();
		System.out.println();
	}
}
数据库的组件。

对于数据库不同version的更新值得借鉴。

package com.example.dbcommon.dao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.v7.internal.widget.ActivityChooserModel.HistoricalRecord;

public class DBHelper extends SQLiteOpenHelper {

	private static final String NAME = "ithm.db";
	private static final int START_VERSION = 1;
	private static final int CURRENT_VERSION = 2;
	public DBHelper(Context context) {
		super(context, NAME, null, CURRENT_VERSION);
		// TODO Auto-generated constructor stub
	}

	//新闻表: 主键 + 标题 + 摘要
	public static final String TABLE_ID = "id";
	
	public static final String TABLE_NEWS_NAME = "news";
	public static final String TABLE_NEWS_TITLE = "titile";
	public static final String TABLE_NEW_SUMMARY = "summary";
	
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		// TODO Auto-generated method stub
			db.execSQL("CREATE TABLE" + TABLE_NEWS_NAME + "(" + //
			TABLE_ID + " integer primary key autoincrement, " +// 
			TABLE_NEWS_TITLE + "varchar(50), " + //
			TABLE_NEW_SUMMARY + "varchar(200))"//
		);
		onUpgrade(db, START_VERSION, CURRENT_VERSION);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
		//更新
		//数据库版本管理:1.0(一张表),2.0(两张表)
		//模拟两种用户
		//老用户:1.0
		//新用户:2.0
		//老用户会更新,没有问题,新用户只有更新后的表,更新前的表就没有
		
		//希望:不需要总是考虑老用户,每次升级数据库操作是什么
		switch(oldVersion){
		case START_VERSION:
			
		case CURRENT_VERSION:
			
		case 3:
		case 4:
			break;
		}
	}

}




© 著作权归作者所有

共有 人打赏支持
chenruibing
粉丝 12
博文 201
码字总数 109101
作品 0
潮州
Java for Web学习笔记(一零三):Spring框架中使用JPA(3)JPA仓库

小例子 我们使用之前JPA小例子的数据库,有三个表Authors,Books和Publishers。先对表Author进行数据读写,读写无非就是增删改查,也就是CRUD。之前,我们已经如何进行Entity和数据库表格的对...

flowingflying ⋅ 2017/12/30 ⋅ 0

baomidou/mybatis-plus

为简化开发工作、提高生产率而生 简介 | Intro Mybatis 增强工具包 - 只做增强不做改变,简化操作 技术讨论 QQ 群 576493122 优点 | Advantages 无侵入:Mybatis-Plus 在 Mybatis 的基础上进...

baomidou ⋅ 2016/01/25 ⋅ 0

XiaoBingBy/bing-upms

简介 Bing-UPMS是一个轻量级的Spring Boot快速开发平台,学习简单、轻量级、易扩展;使用最新技术。 DEMO Bing-UPMS DEMO-----------企业站点 Demo Bing-UPMS + 在线学习系统 点击观看 OSS ...

XiaoBingBy ⋅ 2017/11/05 ⋅ 0

baomidou/mybatisplus-spring-boot-starter

#mybatisplus-spring-boot-starter mybatisplus-spring-boot-starter 为 Mybatis-Plus 快速集成 spring-boot 简化配置而生,不再需拿 MyBatis 和 Hibernate 相比,mybatis-plus 作为 mybati......

baomidou ⋅ 2017/05/05 ⋅ 0

Hibernate 增强工具包--Hibernate-Plus

简介 | Intro Hibernate 增强工具包 - 只做增强不做改变,更加精简持久层CRUD操作 优点 | Advantages 纯正血统:完全继承原生 Hibernate 的所有特性 最少依赖:仅仅依赖 Hibernate 自动生成代...

青苗 ⋅ 2016/12/06 ⋅ 3

Hibernate-Plus 发布 1.0.0.Final

简介 | Intro Hibernate 增强工具包 - 只做增强不做改变,更加精简持久层CRUD操作 优点 | Advantages 纯正血统:完全继承原生 Hibernate 的所有特性 最少依赖:仅仅依赖 Hibernate 自动生成代...

青苗 ⋅ 2016/12/06 ⋅ 10

蓝房子 0.0.3 发布,新式社区程序

蓝房子 0.0.3 发布 蓝房子: 一个轻量级的,关注于移动互联网的,易于集成的新式社区程序。 基于Symfony框架+PHP/PostgreSQL开发 此版本主要是针对技术架构做的重构,重构后的架构扩展性更强...

和风赛跑 ⋅ 2014/11/28 ⋅ 27

mybatis 通用CRUD的替换方法

http://git.oschina.net/alexgaoyh/MutiModule-parent 代码此次变更较大,使用了mybatis-generator-maven-plugin 插件,把之前多模块项目中的domain部分删除,将这一部分代码整合到persise部...

alexgaoyh ⋅ 2015/04/22 ⋅ 1

spring-boot-nutz-starter 1.r.62发布

更新内容: 和 spring-boot 本身依赖的 jackson 和平共处 选择性开启 nutz-json 的支持 让 nutz-json 的配置可以排除指定的强依赖其他 json 库的类 解决打 jar包运行情况下nutz-dao 无法读取...

Kerbores ⋅ 2017/07/18 ⋅ 3

mybatis-generator 插件扩展,生成支持多种数据库的分页功能

背景: 在使用mybatis的过程中,考虑到整合的框架在后期使用的过程中,有可能是需要兼容到多种数据库的,在这种前提条件下,完成通用CRUD功能的编写,本文前期先考虑到不同数据库针对分页功能...

alexgaoyh ⋅ 2015/11/09 ⋅ 1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

一张图看懂CDN全站加速产品解决方案

原文链接 本文为云栖社区原创内容,未经允许不得转载。

阿里云云栖社区 ⋅ 16分钟前 ⋅ 0

一张图看懂CDN全站加速产品解决方案

原文链接

猫耳m ⋅ 17分钟前 ⋅ 0

开启Swarm集群以及可视化管理

在搭建的两台coreos服务器上开启swarm集群 前置条件: docker均开启2375端口 同一个局域网内 主服务器上安装Portainer容器 安装Portainer容器执行: docker run -d -p 9000:9000 --restart=a...

ykbj ⋅ 34分钟前 ⋅ 0

单例设计模式

1、单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例 2、饿汉式单例类 在这个类被加载时,静态变量instance会被初始化,此时类的私有构造子会被调用 饿汉式是典型...

职业搬砖20年 ⋅ 40分钟前 ⋅ 0

前端基础(四):前端国际规范收集

字数:1142 阅读时间:5分钟 前言 由于前端技术的灵活性和杂乱性,导致网上的许多解决方案不够全面甚至是完全错误,容易起到误导作用。所以,我对搜索到的解决方案往往是存疑态度。那么,如何...

老司机带你撸代码 ⋅ 42分钟前 ⋅ 0

Failed to open/create Network-VirtualBox Host-Only

虚拟机版本 : Oracle Vm VirtualBox 5.2.12 报错时机:开网卡二,重启虚拟机报错 "Failed to open/create the internal network 'HostInterfaceNetworking-VirtualBox Host-Only Ethernet Ada......

p至尊宝 ⋅ 45分钟前 ⋅ 0

springMVC接收表单时 Bean对象有Double Int Char类型的处理

前台ajax提交表单price为double类型 后台controller就介绍不到 400错误 前台 实体类: public class ReleaseMapIconConfig{ private String id; private long maxValue; private long minVal......

废柴 ⋅ 50分钟前 ⋅ 0

ZOOKEEPER安装

工作需要在ubuntu上配置了一个zookeeper集群,有些问题记录下来。 1. zookeeper以来java,所以首先要安装java。但是ubuntu系统有自带的jdk,需要通过命令切换java版本: $ sudo update-alter...

恰东 ⋅ 53分钟前 ⋅ 0

linux 进程地址空间的一步步探究

我们知道,在32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间。其实,这个4G的地址空间是不存在的,也就是我们所说的虚拟内存空间。 那虚拟内存空间...

HelloRookie ⋅ 54分钟前 ⋅ 0

myatis #{}与${}区别及原理

https://blog.csdn.net/wo541075754/article/details/54292751

李道福 ⋅ 57分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部