开发原则
(1)Util层:工具层(读写数据库、文件、验证等)
(2)Dao层:负责数据库的处理。SQL语句的编写,处理查询结果。涉及到数据库一般都在Dao层
提取一个BaseDao封装数据库的所有操作。
子类Dao负责责编写SQL语句。
(3)Service层:业务逻辑层,用于处理异常,对应的是App中所有的功能。
(4)View层:Activity,用于和用户交互显示数据。
(5)原则上每一张表都有自己独立的一套内容。
今天讲的内容主要是和查询相关:
(1)首先建立如下图所示的结构。
图1.1 总体结构
(2)首先编写DBManager方法,注意要继承SQLiteOpenHelper:
private static String name="neu.db";
private static int version=1;
public DBManager(Context context)
{
super(context, name, null, version);
}
/**
* 在创建表的时候需要添加一些拓展列,以备将来使用
* 数据库设计的三大范式(只要遵循2NF即可)
* powerdesigner
*/
@Override
public void onCreate(SQLiteDatabase db)
{
String sql="create table user_info"
+"("
+"user_id integer primary key,"
+"user_name text,"
+"user_pwd text,"
+"ext_01 text,"
+"ext_02 text,"
+"ext_03 text"
+")";
db.execSQL(sql);
sql="create table book_info"
+"("
+"book_no integer primary key,"
+"book_name text,"
+"book_price real"
+")";
db.execSQL(sql);
}
/**
* 实际开发中该方法没有任何意义
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
String sql="drop table if exists user_info";
db.execSQL(sql);
sql="drop table if exists book_info";
db.execSQL(sql);
onCreate(db);
}
(2)创建BaseDao类:
private DBManager manager;
private SQLiteDatabase db;
public BaseDao(Context context)
{
//构建DBManager对象时需要一个上下文
//通过context来指定目录
//context.getPackageName()获取app程序所在的包名
manager=new DBManager(context);
}
//数据库的操作CRUD分为两大类
//修改操作insert、delete、update、drop
//查询操作select
/**
* 用于执行修改操作的方法
*/
protected final void executeUpdate(String sql,Object...args)
{
db=manager.getWritableDatabase();
db.execSQL(sql);
db.close();
}
(3)创建UserInfoDaoImpl类:
public UserInfoDaoImpl(Context context)
{
super(context);
}
public void save(String name,String pwd)
{
String sql="insert into user_info(user_name,user_pwd)"
+"values(?,?)";
super.executeUpdate(sql, name,pwd);
}
(4)创建UserInfoService类:
private UserInfoDaoImpl userInfoDaoImpl;
public UserInfoService(Context context)
{
userInfoDaoImpl=new UserInfoDaoImpl(context);
}
public boolean doReg(String name,String pwd)
{
boolean flag=false;
try
{
this.userInfoDaoImpl.save(name, pwd);
flag=true;
}
catch (Exception e)
{
e.printStackTrace();
//把异常信息做记录或者发邮件。
}
return flag;
}
(5)创建MainActivity类,用于和用户交互的类。
private Button btnwrite;
private Button btnread;
private UserInfoService userInfoService;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findView();
setListener();
}
private void findView()
{
this.btnread=(Button) findViewById(R.id.button_read);
this.btnwrite=(Button) findViewById(R.id.button_write);
this.userInfoService=new UserInfoService(this);
}
/**
* 操作SQLite数据库时最常出现的问题是SQL语句编写错误
*/
private void setListener()
{
this.btnwrite.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
String name="zhangsan";
String pwd="123456";
boolean flag=userInfoService.doReg(name, pwd);
if(flag)
{
Toast.makeText(MainActivity.this, "Success to register", 1000).show();
}
else
{
Toast.makeText(MainActivity.this, "Fail to register", 1000).show();
}
}
});
}
(6)执行查询操作需要在BaseDao类中添加executeQuery()方法:
使用List结构嵌套HashMap结构。使用游标进行查询。
游标很灵活可以根据游标获取游标的列数,游标的名。
注意:最后要把游标关闭。
protected final List<HashMap<String,String>>executeQuery(String sql,String...args)
{
List<HashMap<String,String>>data=new ArrayList<HashMap<String,String>>();
db=manager.getReadableDatabase();
//返回值为游标其实就是java中的resultSet
Cursor cur=db.rawQuery(sql, args);
//获取从查询的所有列名
String []names=cur.getColumnNames();
//获取查询的列数
int n=cur.getColumnCount();
//获取查询的记录总条数
int m=cur.getCount();
//moveToNext移动到下一条记录,如果有返回为true,否则为false
//用于保存每一行中的数据,存储方式已列名为key,数据为value
HashMap<String,String>item=null;
while(cur.moveToNext())
{
//获取数据
item=new HashMap<String, String>();
for(String name:names)
{
//根据列名获取该列所在的下标在根据下标获取对应的数据
String value=cur.getString(cur.getColumnIndex(name));
item.put(name, value);
}
//保存该行数据
data.add(item);
}
cur.close();
return data;
}
(7)在UserInfoImpl中添加查询操作:
public List<HashMap<String,String>>findAll()
{
//不允许使用*号
String sql="select user_id,user_name,user_pwd from user_info";
List<HashMap<String,String>>data=super.executeQuery(sql);
return data;
}
public List<HashMap<String,String>>checkLogin(String name,String pwd)
{
//编写SQL语句时换行就加空格
String sql="select user_id,user_name,user_ped from user_info"
+" where user_name=? and user_ped=?";
return super.executeQuery(sql, name,pwd);
}
如何打包导出jar包实现通用。
在程序中有一种文件叫做.properties为后缀的文件,是以键值对的方式保存数据。同时java api中提供了提取该类型文件的工具。
db.properties。
dname=www.dp
version=1;
提供了一个以键取值的方法。只要读db.properties文件即可。
该文件保存的位置android项目中有一个asset目录,如图1.2所示。
图 1.2 asset
资源文件中如果要换行显示数据的话,在换行之前添加\,在换行。
编写db.properties
dbname=neu.db
version=1
create_sql=create table user_info\
(\
user_id integer primary key,\
user_name text,\
user_pwd text,\
ext_01 text,\
ext_02 text,\
);\
create table book_info\
(\
book_id integer primary key,\
book_name text\
)
drop_sql=drop table user_info;drop table book_info
读取db.properties中的数据。
java中提供了一个类专门来读这种文件,Properties就是读取properties文件的类。
//创建对象
Properties pro=new Properties();
//加载要解析的.properties
pro.load(输入流);
String dbname=pro.getproperty("dbname");
建立了db.properties后的读取过程如下
其中在onCreate和onUpgrade方法中有重复的过程。java强大的功能可以将重复的代码整合为一个方法。
选中要打包的代码,点击鼠标的右键选择Refactor,在找Extract Method即可将代码打包。
例如如下代码:它们统一的操作为execsql。在onCreate和onUpgrade中只需为其传递参数即可。
private static String name;
private static int version;
private static String create_sql;
private static String drop_sql;
/**
* 静态块,在类加载的时候执行,只执行一次
*/
static
{
//创建读取.properties文件的对象
Properties pro=new Properties();
//加载要解析的.properties
//从assets文件中读取资源
//把src下名为db.properties的文件构建为输入流
//文件名前必须添加/,表示src的根目录
InputStream in=DBManager.class.getResourceAsStream("/db.properties");
try
{
pro.load(in);
//从资源文件中获取数据
name=pro.getProperty("dbname");
version=Integer.parseInt(pro.getProperty("version"));
create_sql=pro.getProperty("create_sql");
drop_sql=pro.getProperty("drop_sql");
}
catch (IOException e)
{
e.printStackTrace();
}
}
public DBManager(Context context)
{
super(context, name, null, version);
}
/**
* 在创建表的时候需要添加一些拓展列,以备将来使用
* 数据库设计的三大范式(只要遵循2NF即可)
* powerdesigner
*/
@Override
public void onCreate(SQLiteDatabase db)
{
String [] sqls=create_sql.split(";");
execsql(db, sqls);
}
private void execsql(SQLiteDatabase db, String[] sqls) {
if(sqls!=null)
{
for(String sql:sqls)
db.execSQL(sql);
}
}
/**
* 实际开发中该方法没有任何意义
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
String [] sqls=drop_sql.split(";");
execsql(db, sqls);
onCreate(db);
}
在打包之前需要编写说明文件,以便让用户知道如何使用导出的包。
在项目上点击鼠标右键,选中New-File。建一个.txt文件
文件如图1.3所示:
图 1.3 说明文件
在项目上点击鼠标右键,选中Export。之后选中java,再选中java file,如图1.4所示,选择自己想导出的.java文件。
图 1.4 JAR Export
导包成功:
图 1.5 导出成功