引言

经过几天的面向百度和csdn,以及和无数java中的对象谈恋爱,终于弄清除了JDBC连接数据库的来龙去脉。因此本帅决定记录下本帅从搭建服务器到运行到Android摸索的全过程,也算给小白们些许福利!话不多说,让我们开始吧!

步骤

JDBC(Java DataBase Connection)的前提工作

a. JDBC如果没有服务器,首先需要搭建本地的局域网服务器

详情见传送门大娃

传送门大娃子本地服务器的搭建

b. 搭建好服务器以后,需要创建可远程访问mysql数据库权限的用户

详情见传送门二娃

传送门二娃子创建可远程访问mysql数据库权限的用户

c. 当完成好前面两步以后,需要下载MySQL Connector for Java(Mysql 提供给Java连接数据库的接口)驱动,并在Android studio 中配置好,具体配置见传送门三娃

传送门三娃下载并配置Mysql connector for java驱动接口

连接JDBC

d. 当完成好上述JDBC连接的准备工作以后,就可以着手连接JDBC了

1.首先我们需要在mysql中创建数据库,和数据表。(如果数据表中没法插入中文,请参考传送门四娃。)
传送门四娃phpMyAdmin中文无法插入的编码问题的解决
2.写JDBC加载驱动获得JDBC连接的代码
Class.forName(com.mysql.jdbc.Driver) 通过反射加载驱动类(按照类名加载)
在这里插入图片描述
在这里插入图片描述
Connection connection = DriverManager.getConnection(url,username,password);
3.获取连接中的三个参数url,username,password
String url = “jdbc:mysql://服务器ip地址:数据库的访问端口/数据库名称”
String username = 创建的可远程访问mysql权限的用户的用户名
String password = 创建的可远程访问mysql权限的用户的密码
其中 服务器ip地址的获得 来自 dos命令下输入ipconfig,
数据库的访问端口来自登入phpMyadmin下,上方显示的端口(一般为3306,如果你未更改过端口的话)
在这里插入图片描述
通过以上的步骤,小伙伴们就能够连上远程服务器的mysql数据库的具体某个数据库啦,具体步骤请参考传送门五娃
传送门五娃连接远程mysql数据库中的具体某个数据库

e. 连接上mysql远程数据库中的具体数据库后,对该数据库的表的操作,需要掌握的知识:

statement(statement(sql注入),preparedstatement等)
Resultset(查询的结果集)等
由于发现JDBC的增删改查的代码存在同一耦合的代码,为4中所提到的加载驱动获取连接以及资源使用后的释放代码(connection,statement,resultset),所以单独提取除了一个工具类JDBCUtil,详情见传送门六娃:

传送门六娃JDBC增删改查操作以及JDBCUtil封装工具类

f. 提取出JDBC工具类以及实现JDBC增删改查代码以后,我们需要设置两个测试,

一个是面向Android studio的控制台的测试类(有Main方法的类,输出在Android studio控制台上)
一个是面向Android 的测试Activity(理论上来讲,能在main中运行测试以后,基本也能在手机的Activity中运行)
在这里插入图片描述
先在有主方法的类中测试JDBC的增删改查操作是否没有问题,部分测试代码如下:(主要提供思路,小伙伴们最好自行写代码测试哟!)

	package com.example.paoduantui.JDBC.testJDBC; 
	 
	 
	import android.os.SystemClock; 
	 
	import com.example.paoduantui.JDBC.JDBCDAO.PositionDBDao; 
	import com.example.paoduantui.JDBC.JDBCDAO.TaskDBDao; 
	import com.example.paoduantui.JDBC.JDBCDAO.UserDBDao; 
	import com.example.paoduantui.JDBC.JDBCDB.PositionDB; 
	import com.example.paoduantui.JDBC.JDBCDB.TaskDB; 
	import com.example.paoduantui.JDBC.JDBCDB.UserDB; 
	import com.example.paoduantui.Task; 
	 
	import java.util.List; 
	 
	//测试JDBCDao类 
	/** 
	 * 创建了四个线程,分别执行了增删改查操作 
	 * 测试了dao类 
	 * main方法中能调用的,Activity中也可以 
	 * */ 
	 
		public class testJDBCDao { 
	 
	       public static void main(String[] args){ 
	 
	           //插入线程 
	           new Runnable() { 
	               @Override 
	               public void run() { 
	                  //TaskDB taskDB = new TaskDB(1,1,"张大帅比",'1',"张斌真帅","","2015-06-14","2015-06-14",'7'); 
	                   PositionDB positionDB = new PositionDB(1,1,1,1,"","",""); 
	                   int result= PositionDBDao.insert(positionDB); 
	                   if(result==1) System.out.print("插入数据成功!"); 
	               } 
	           }.run(); 
	 
	            //查询线程 
	           new Runnable() { 
	               @Override 
	               public void run() { 
	                   List<TaskDB> list = TaskDBDao.getAll(); 
	                   for(int i= 0;i<list.size();i++){ 
	                       System.out.println(list.get(i).getId()+list.get(i).getUsername()); 
	                   } 
	               } 
	           }.run(); 
	 
	 
	           //删除线程 
	           new Runnable() { 
	               @Override 
	               public void run() { 
	                   TaskDB taskDB1=new TaskDB(9,1,"张斌斌",1,"张斌斌摔倒的","","","",7); 
	                   int result1 = TaskDBDao.deleteByTaskId(taskDB1); 
	                   if(result1==1)System.out.println("删除数据成功!!"+taskDB1.getTaskid()); 
	               } 
	           }.run(); 
	 
	           //更新线程 
	           new Runnable() { 
	               @Override 
	               public void run() { 
	                   TaskDB taskDB1=new TaskDB(1,1,"张斌斌",1,"张斌斌摔倒的","","","",7); 
	                   int result1 = TaskDBDao.updateByTaskId(taskDB1); 
	                   System.out.println("更新数据成功!!"+taskDB1.getTaskid()); 
	               } 
	           }.run(); 
	 
	 
	       } 
	 
	    } 

将没有问题的方法再放入Android 的Activity中测试,此时,会发现在含有主方法的类中能运行的某些方法在Android设备上运行会闪退,
究其原因有以下几种可能:(通过检查一一排除)

1.连接远程mysql服务器,本质是TCP连接(访问,返回数据),因此需在AndroidManifest.xml文件中添加网络权限
2.需要添加连接JDBC的许可协议(本帅也不知道这是什么鬼,望大神告知)(在需要用到JDBC的Activity的oncreat加载布局后添加上以下代码:)

	 //添加许可协议,不加的话,闪退 	 StrictMode.ThreadPolicy policy = new 
 StrictMode.ThreadPolicy.Builder().permitAll().build(); 
 StrictMode.setThreadPolicy(policy); 
  1. 当第一次进入界面可以成功使用JDBC的操作,而第二次进去会闪退,主要是因为,Android不支持将JDBC放在主线程中,因此需要调用线程来完成JDBC的操作

当在含有主方法的类中以及Activity中均测试完以后,意味着Android端可以利用JDBC来成功访问远程mysql远程数据库啦!!(贴上我用来测试的Activity代码)

package com.example.paoduantui.JDBC.testJDBC; 
 
import android.os.StrictMode; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
import android.widget.Toast; 
 
import com.example.paoduantui.JDBC.JDBCDAO.TaskDBDao; 
import com.example.paoduantui.JDBC.JDBCDAO.UserDBDao; 
import com.example.paoduantui.JDBC.JDBCDB.TaskDB; 
import com.example.paoduantui.JDBC.JDBCDB.UserDB; 
import com.example.paoduantui.R; 
 
import java.util.List; 
 
 
//在main方法中或在activity中不能将JDBC操作数据库放在主线程里 
 
public class testJDBCActivity extends AppCompatActivity { 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_test_jdbc); 
 
 
        final TextView textView = findViewById(R.id.textView); 
        Button insert =findViewById(R.id.insert); 
        Button delete =findViewById(R.id.delete); 
        Button query = findViewById(R.id.query); 
        Button update = findViewById(R.id.update); 
 
         //添加许可协议,不加的话,闪退 
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
            StrictMode.setThreadPolicy(policy); 
 
 
            //开启新线程,插入数据 
        final Runnable runnable1=new Runnable() { 
            @Override 
            public void run() { 
                TaskDB taskDB = new TaskDB(1,1,"张大帅比",'1',"张斌真帅","","2015-06-14","2015-06-14",'7'); 
 
                int result=TaskDBDao.insert(taskDB); 
                if(result==1)Toast.makeText(testJDBCActivity.this,"插入数据成功!",Toast.LENGTH_LONG).show(); 
                else Toast.makeText(testJDBCActivity.this,"不要在点击了,已经插入成功了!!",Toast.LENGTH_LONG).show(); 
            } 
        }; 
 
        //开启新线程,删除数据 
        final Runnable runnable2 = new Runnable() { 
            @Override 
            public void run() { 
                TaskDB taskDB = new TaskDB(1,1,null,0,null,null,null,null,0); 
 
                int result = TaskDBDao.deleteByTaskId(taskDB); 
                if(result==1) Toast.makeText(testJDBCActivity.this,"删除数据成功!",Toast.LENGTH_LONG).show(); 
            } 
        }; 
 
            //开启新线程,连接JDBC,防止主线程阻塞,查询 
            final Runnable runnable = new Runnable() { 
                @Override 
                public void run() { 
 
                    String str=""; 
                    List<TaskDB> list = TaskDBDao.getById(1, 0); 
                    for (int i = 0; i < list.size(); i++) { 
                        str += list.get(i).getId() + list.get(i).getUsername(); 
                    } 
                    //Toast.makeText(testJDBCActivity.this, str, Toast.LENGTH_LONG).show(); 
                    textView.setText(str); 
 
                } 
            }; 
 
            //更新线程 
            final Runnable runnable3 = new Runnable() { 
                @Override 
                public void run() { 
                    TaskDB taskDB = new TaskDB(2,1,"彬彬",0,"","","","",0); 
 
                    int result = TaskDBDao.updateByTaskId(taskDB); 
                    if(result==1) Toast.makeText(testJDBCActivity.this,"更新成功!!",Toast.LENGTH_LONG).show(); 
                } 
            }; 
 
            insert.setOnClickListener(new View.OnClickListener() { 
                @Override 
                public void onClick(View v) { 
                    runnable1.run(); 
                } 
            }); 
 
            delete.setOnClickListener(new View.OnClickListener() { 
                @Override 
                public void onClick(View v) { 
                    runnable2.run(); 
                } 
            }); 
 
            query.setOnClickListener(new View.OnClickListener() { 
                @Override 
                public void onClick(View v) { 
                    runnable.run(); 
                } 
            }); 
 
            update.setOnClickListener(new View.OnClickListener() { 
                @Override 
                public void onClick(View v) { 
                    runnable3.run(); 
                } 
            }); 
 
            //Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); 
        } 
} 

在这里插入图片描述

g.根据数据库中所建的表建相应的实体类DB类(表中字段即为类中的成员变量)
package com.example.paoduantui.JDBC.JDBCDB; 
 
 
//数据库user表的实体类 
public class UserDB { 
 
    private int id;//id 
    private String username;//用户名 
    private String password;//密码 
    private  int image;//头像 
 
    //insert into user(id,username,password,image) values (getId,getUsername,getPassword,getImage); 
    //表名可以通过解析对象userDB,规定user_DB为其对象,解析对象即可 
    //通过占位符,四个占位符,for(int i = 1;i<count;i++) ?, 
    //ps.setObject(1,getId) 通过反射获取 
    //ps.setObject(4,getImage) 
    private final int count = 4;//该表有四个字段 
 
    public UserDB() { 
    } 
 
 
    //构造函数以及其getter setter 方法 
 
    public UserDB(int id, String username, String password, int image) { 
        this.id = id; 
        this.username = username; 
        this.password = password; 
        this.image = image; 
    } 
 
    public int getId() { 
        return id; 
    } 
 
    public void setId(int id) { 
        this.id = id; 
    } 
 
    public String getUsername() { 
        return username; 
    } 
 
    public void setUsername(String username) { 
        this.username = username; 
    } 
 
    public String getPassword() { 
        return password; 
    } 
 
    public void setPassword(String password) { 
        this.password = password; 
    } 
 
    public int getImage() { 
        return image; 
    } 
 
    public void setImage(int image) { 
        this.image = image; 
    } 
 
 
 
} 
f.根据该表创建出相应的数据库操作类Dao类(本帅一般创建增删改查(其中查又细分为查所有getAll,按条件查等,getById,getCondition(如模糊查找)等)类)
package com.example.paoduantui.JDBC.JDBCDAO; 
 
import android.widget.Switch; 
 
import com.example.paoduantui.JDBC.JDBCDB.UserDB; 
import com.example.paoduantui.JDBC.JDBCUtil; 
 
import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.util.ArrayList; 
import java.util.List; 
 
 
//user表的数据库操作类 
/** 
 * 里面的方法全为静态方法,用 UserDBDao.方法名 直接调用 
 * insert方法(增),deleteById方法(删),updateById方法(改),(参数均为UserDB) 
 * getAll(返回为UserDB的链表集合)(无参数)以及getById(返回为UserDB的链表集合)(_id ,type)(查) 
 * */ 
public class UserDBDao { 
 
    private static  Connection  connection;//获取连接(跑断腿App的连接) 
    private static  PreparedStatement ps;//准备好的sql陈述 
    private  static ResultSet rs;//结果集 
 
    //增 
    /** 
     * 返回int类型的insert数据库操作 
     * 参数为UserDB 
     * */ 
    public static int insert(UserDB userDB){ 
 
        try { 
 
            connection = JDBCUtil.getConnection(); 
            String sql = "insert into user(id,username,password,image) values (?,?,?,?)"; 
            ps = connection.prepareStatement(sql); 
            ps.setObject(1,userDB.getId()); 
            ps.setObject(2,userDB.getUsername()); 
            ps.setObject(3,userDB.getPassword()); 
            ps.setObject(4,userDB.getImage()); 
            int result = ps.executeUpdate(); 
            return result; 
        } catch (SQLException e) { 
            e.printStackTrace(); 
        }finally { 
            JDBCUtil.close(null,ps,connection); 
        } 
 
        return 0; 
    } 
 
    //删 
    /** 
     * 返回int类型的deleteById数据库操作 
     * 参数为UserDB 
     * */ 
    public static int deleteById(UserDB userDB){ 
 
        try { 
            connection = JDBCUtil.getConnection(); 
            String sql = "delete from user where id = ?"; 
            ps = connection.prepareStatement(sql); 
            ps.setObject(1,userDB.getId()); 
            int result = ps.executeUpdate(); 
            return result; 
        } catch (SQLException e) { 
            e.printStackTrace(); 
        }finally { 
            JDBCUtil.close(null,ps,connection); 
        } 
 
        return 0; 
    } 
 
    /** 
     * 返回int类型的updateById数据库操作 
     * 参数为UserDB 
     * */ 
    public static int updateById(UserDB userDB){ 
 
        try { 
            connection = JDBCUtil.getConnection(); 
            String sql = "update  user set username = ? , password = ? , image = ? where id = ?"; 
            ps = connection.prepareStatement(sql); 
            //ps.setObject(1,userDB.getId()); 
            ps.setObject(1,userDB.getUsername()); 
            ps.setObject(2,userDB.getPassword()); 
            ps.setObject(3,userDB.getImage()); 
            ps.setObject(4,userDB.getId()); 
            int result = ps.executeUpdate(); 
            return result; 
        } catch (SQLException e) { 
            e.printStackTrace(); 
        }finally { 
            JDBCUtil.close(null,ps,connection); 
        } 
 
        return 0; 
    } 
 
    /** 
     * 返回List<UserDB>类型的获取表中所有数据的数据库操作 
     * */ 
    public static List<UserDB> getAll(){ 
 
        List<UserDB> list = new ArrayList<>(); 
 
        try { 
            connection = JDBCUtil.getConnection(); 
            String sql = "select * from user order by id desc";//降序排列,使得每次第一条记录永远是最新的记录 
            ps = connection.prepareStatement(sql); 
            rs = ps.executeQuery(); 
            while (rs.next()){ 
                int id = rs.getInt(1); 
                String username = rs.getString(2); 
                String password = rs.getString(3); 
                int image = rs.getInt(4); 
                UserDB userDB = new UserDB(id,username,password,image); 
                list.add(userDB); 
            } 
            return  list; 
        } catch (SQLException e) { 
            e.printStackTrace(); 
        }finally { 
            JDBCUtil.close(rs,ps,connection); 
        } 
        return  null; 
    } 
 
    /** 
     * 返回List<UserDB>类型的根据不同id的类型获取表中数据的数据库操作 
     * 其中参数_id 表示id的值,type表示id的类型 0:id(用户id),1:taskid(任务id),2:jdr_id(接单人id) 
     * */ 
    public static List<UserDB> getById(int _id,int type){ 
 
 
        String selection = null; 
        List<UserDB> list = new ArrayList<>(); 
 
        switch (type){ 
            case  0: 
                selection = "id"; 
                break; 
            case  1: 
                selection="taskid"; 
                break; 
            case  2: 
                selection="jdr_id"; 
                break; 
        } 
 
        try { 
            connection = JDBCUtil.getConnection(); 
            String sql = "select * from user where "+ selection + "= ? ";//通过拼接的sql来查询不同id下的数据 
            ps = connection.prepareStatement(sql); 
            ps.setObject(1,_id); 
            ResultSet rs = ps.executeQuery(); 
            while (rs.next()){//注意,此处的结果集不同于sqlite的游标集,下标是从1开始的 
                int id = rs.getInt(1); 
                String username = rs.getString(2); 
                String password = rs.getString(3); 
                int image = rs.getInt(4); 
                UserDB userDB = new UserDB(id,username,password,image); 
                list.add(userDB); 
            } 
            return  list; 
        } catch (SQLException e) { 
            e.printStackTrace(); 
        }finally { 
            JDBCUtil.close(rs,ps,connection); 
        } 
        return  null; 
    } 
 
} 

至此,JDBC到这儿就完美收官啦!期待与小伙伴们的再次相遇!

发布评论

分享到:

IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

使用ipad上的termius app直连win10电脑进行远程编程!!!讲解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。