这一阵没有更新博客是十一了和朋友出去玩一下,其实博主是个标准宅男,像十一这种放假应该在家好好休息的。但说实话这次秋招有点自闭<难受>,也就和朋友出去玩玩,顺带散散心。玩的时候偶尔看一下博客,发现有小伙伴私信博主,说实话还是有点小开心的。问了博主关于数据库同步的问题,这个博主之前也是做过。但是由于6月份的时候更新了一波电脑,不光记录没了,就连mySQL都没了<尴尬>。玩完回来就马上下载了一波mySQL与navicat(可以比较简单的操作mySQl),然后开始实现数据库同步的功能。基本逻辑实现之后,发现运行时无法连接上mySQl,也上网查了许多资料,试了好多方法。但还是不太行,但也不能让小伙伴等太长时间,就打算先说一下博主的思路与代码把。希望能帮到大家。(等博主mySQL连上时候,会告诉大家为什么连不上,也帮大家踩踩坑)
博主已经连上了mysql:https://blog.csdn.net/qq_29226403/article/details/103214832
1.思路:
由于Android由本地的数据库,所以博主的思路就是。设计两个按钮,一个上传按钮,一个下载按钮来实现同步。当点击上传按钮的时候,将Android中数据库的内容拷贝到mysql中,当点击下载的时候将mysql中的数据拷贝到Android的数据库中。其实博主百度了一下,也有一个按钮通过时间戳实现的,但由于博主这mysql没连上。也不敢轻易给大家代码,也不知道可不可以实现。Android中的数据库有很多,这里博主用的为第三方的数据库LitePal,因为感觉比较简单。
2.具体实现:
下面说一下LitePal的使用。
步骤1:添加依赖
implementation 'org.litepal.android:core:1.4.1'
步骤2:配置文件:在main文件夹中新建一个assets文件,在里面新建文件litepal.xml。
<litepal>
<dbname value="myBase"></dbname>
<version value="1"></version>
<list>
<mapping class="com.example.jdbc_test.people"></mapping>
</list>
</litepal>
这段代码还是比较好理解的,dbname就是数据库的名字,version为数据库的版本,比如现在数据库是版本1.如果你要在数据库中新加一个字段的话,需要把1改为比1大的数才行,要么是不行的。下面的mapping就是类名了,这里注意是类的全名,不是包名,比如类是people,包是com.example.jdbc_test,这里就添com.example.jdbc_test.people。这就是简单的地方了,把一个类当作一个表格,用起来很方便了就。如果发现关键字都是红的的话,把鼠标放在</litepal>的后边,按下回车等1秒应该就好了。
步骤3:在配置文件AndroidMainfest.xml中在Android:allowBackup="true"的上一行添加,
android:name="org.litepal.LitePalApplication"
这样可以保证所有的功能都是可以使用的。
步骤4:建立表people的类people,
import org.litepal.crud.DataSupport;
public class people extends DataSupport {
public int number;
public String name;
public void setNumber(int number)
{
this.number=number;
}
public void setName(String name)
{
this.name=name;
}
public int getNumber()
{
return number;
}
public String getName()
{
return name;
}
}
让类继承DataSupport是为了可以对表进行操作。(增删改查),具体操作在之后的代码里面详细说明。
先来添加按钮的点击事件,在Main中
这里注意一点连接数据库为耗时操作,需要在子线程中进行。
Button upButton=findViewById(R.id.upButton);
Button downButton=findViewById(R.id.downButton);
upButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
// 创建一个线程
new Thread(new Runnable()
{
@Override
public void run()
{
DBUtils dbUtils = new DBUtils();
dbUtils.up();
}
}).start();
}
});
downButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
// 创建一个线程
new Thread(new Runnable()
{
@Override
public void run()
{
DBUtils dbUtils = new DBUtils();
dbUtils.down();
}
}).start();
}
});
然后再来实现类DButils类把,
import org.litepal.crud.DataSupport;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class DBUtils {
private static String driver = "com.mysql.jdbc.Driver";//mysql驱动
private static String url = "jdbc:mysql://192.168.1.106:3306/test";//mysql数据库连接url,192.168.1.106为自己电脑的ip,test为数据库名。
private static String user = "local";//用户名
private static String password = "123456";//密码
private static Connection getConnection(){
Connection conn = null;
try {
Class.forName(driver);//驱动:告诉电脑是什么数据库
conn = DriverManager.getConnection(url,user,password);//连接数据库
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return conn;
}
public void up()
{
Connection conn = getConnection();
Statement st = null;
try {
st = conn.createStatement();
String sql = "delete from student";
PreparedStatement ps = conn.prepareStatement(sql);//先将mysql全部删除,在将litepal数据库添加进去。
ps.executeUpdate();//对sql数据库进行操作。
List<people> list= DataSupport.findAll(people.class);//取出数据库people的数据。
for(people p:list)//遍历集合,将每一个litepal的值都赋值给mySQL。
{
sql = "insert into student(number,name) values(?,?)";
ps = conn.prepareStatement(sql);
ps.setInt(1, p.getNumber());
ps.setString(2, p.getName());
ps.executeUpdate();//进行对数据库操作时用这个方法启动。
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (st != null) {
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public void down()
{
Connection conn = getConnection();//数据库连接
Statement st = null;
try {
DataSupport.deleteAll(people.class);//这个方法删除表people的所有数据。
st = conn.createStatement();
String sql = "select * from student";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();//对sql数据库进行操作,进行查询的话用这个方法启动。而rs可以保存查询的结果
int count = rs.getMetaData().getColumnCount();//这个方法返回的是列的总和。
while (rs.next()){//遍历查询结果,next方法就是往下移一个,说白了就是看下一行有没有东西。
// 注意:下标是从1开始的
people p=new people();//每一行都重新定义一个p
for (int i = 1;i <= count;i++){
String field = rs.getMetaData().getColumnName(i);//获取第i列的列名。
if(field.equals("name"))
{
String string= rs.getString(field);//这个方法获取当列名为field时的值。由于name的类型为String,所以用getString。
p.setName(string);
}
if(field.equals("number"))
{
int in= rs.getInt(field);//这个方法获取当列名为field时的值。由于number的类型为int,所以用getInt。
p.setNumber(in);
}
}
p.save();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (st != null) {
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
对了,还有添加网络申请权限,在AndroidMainfest.xml中添加。
<uses-permission android:name="android.permission.INTERNET" />
这就是对数据库的同步,至于要以什么方式来显示数据库中的数据,都可以的。比如TextView,recyclerView之类的都是可以的。这里不多说了就,要不博客太长,兄弟们也看不下去了。。。这里的代码真的是仅供参考,兄弟们不要复制代码,由于mySql的连接的失败,无法测试代码,不能保证对不对,但思路都是可行的,如果看完不太懂的话,可以私信或者留言都可以,对了,如果能看出博主在数据库连接上哪里错了的话也可以私信呦。
//如果发现代码错了或有疑问的兄弟们随时欢迎啊。