接口:API。 规范。 定义方法签名。
接口和抽象了的意义上的区别。
抽象类是类,抽象类的目的就是让其他类来继承的。 只要继承从意义上来说就要说通 is a。
接口更趋向于功能。希望某一个类有接口指定的功能,就让这个类实现这个接口。
实现
接口属于java的语言的四大类型之一,而且是非常重要的类型。
语法:
public interface 接口名{
常量
抽象方法
默认方法(JKD1.8开始才有)
}
实例:
public interface Ink {
//常量
public static final int WIDTH = 15;
//在接口中定义一个成员变量,则默认使用 public static final -->常量
int HEIGHT = 20;
//方法默认就是public abstract修饰
public abstract void methodA();
//默认就是抽象方法
void methodB();
//jdk 1.8开始有了默认方法
default void methodC(){
System.out.println("默认方法C");
}
default void methodD(){
System.out.println("默认方法D");
}
}
接口中的普通的方法都默认是抽象方法。
接口不能被实例化(直接创建接口对象)。
接口中所有的成员变量默认都是常量。(必须有初始值,不可以改变)
接口中可以有默认方法(1.8)。默认方法可以有方法体。默认方法都是使用default修饰。
接口的实现
我们可以使用任何一类实现一个接口。当然这个类也可以是抽象类。
如果一个类实现了一个接口,就默认继承了这个接口的默认方法。
如果这个类不是抽象了,则这个类必须实现接口中所有的抽象方法。
如果这个类是抽象类,则可以选择实现接口中的 抽象方法。
非抽象类实现接口:
public class ColorInk implements Ink {
抽象类实现接口:
public abstract class OtherInk implements Ink{
public void methodA() {
System.out.println("选择实现方法methodA");
}
}
接口是多现实的:一个类可以实现多个接口。
1.8之前的接口中是没有默认方法的,所有的方法都是抽象方法,那么一个类实现类两个接口,两个接口中有同样的方法,是不影响的。
案例:
public interface InterB {
void methodA();
}
public interface InterA {
void methodA();
}
public class InterImpl implements InterA,InterB {
但是1.8开始有了默认方法,看看效果:
public interface InterB {
void methodA();
default void methodB(){
System.out.println("InterB - methodB");
}
}
public interface InterA {
void methodA();
default void methodB(){
System.out.println("InterA - methodB");
}
}
要求自己实现一个methodB方法:
public class InterImpl implements InterA,InterB {
接口之间的继承: 接口是可以多继承的
接口可以继承接口。
一个接口可以继承多个其他接口。
多继承,如果只有抽象方法,不会产生冲突
public interface InterA {
void methodA();
}
public interface InterB {
void methodA();
}
public interface InterC extends InterA,InterB {
void methodA();
}
如果两个父接口有同名的默认方法:
接口的使用
接口看上去就是比抽象类更抽象一个类。
接口的作用和抽象类类似,但是抽象更趋向于类。而接口更趋向于功能。
使用上和抽象类几乎相同。
抽象类都是 申明抽象类对象, 创建子类实例。
接口也一样。
实现类的类型转向接口也是向上转型,自动转换。 接口类型转向实现类也是向下转型,需要强制类型转换。
public static void main(String[] args) { //申明接口类型,创建实现类对象 Ink ink = new ColorInk(); ink.methodA();//实现的方法methodA ink.methodB();//实现的方法methodB ink.methodC();//默认方法C ink.methodD();//默认方法D }
tips:如果在实现类中扩展方法
接口的多态:
public interface USB { void turnOn(); void turnOff(); } public class Mouse implements USB { @Override public void turnOn() { System.out.println("鼠标开"); } @Override public void turnOff() { System.out.println("鼠标关"); } } public class Mic implements USB { @Override public void turnOn() { System.out.println("音响开"); } @Override public void turnOff() { System.out.println("音响关"); } } public class Computer { public void openUSB(USB usb){ usb.turnOn(); } public void stopUSB(USB usb){ usb.turnOff(); } } public class Test { public static void main(String[] args) { Computer computer = new Computer(); computer.openUSB(new Mouse()); computer.openUSB(new Mic()); } }
实现类重写默认方法:
public class BlackInk implements Ink{ @Override public void methodA() { System.out.println("黑白墨盒-methodA"); } @Override public void methodB() { System.out.println("黑白墨盒-methodB"); } //重写默认方法 @Override public void methodC() { System.out.println("黑白墨盒-methodC"); } @Override public void methodD() { System.out.println("黑白墨盒-methodD"); } }
测试:
Ink ink = new BlackInk(); ink.methodA(); ink.methodB(); ink.methodC(); ink.methodD();
案例测试:
public class Test { public static void main(String[] args) { InterB inter = new InterImpl(); inter.methodA();//被子类实现 inter.methodB();//接口中的默认方法被重写的 //实现类对象可以直接赋值给任意一个父接口。 InterA ia = new InterImpl(); InterB ib = new InterImpl(); } }
补充:接口中可以定义静态方法。
package com.qidian.demo5; public interface InterA { public static void methodA(){ System.out.println("接口中的静态方法"); } } public class Test { public static void main(String[] args) { //接口中的静态方法 InterA.methodA(); } }
JDBC
JDBC是一套接口。java程序要连接数据库,就要有对应的程序访问对应的数据。但是数据库各不相同,java没有办法开发一套程序对应所有的关系型数据库。
我们访问数据无非就四个操作:增删改查。 --> 增删改,查
定义接口:
public List<Data> queryAll(tableName); public int insert(.....); 只有接口,不做实现....
由数据库开发商实现这些接口。开发商所实现的这一套代码就是JDBC驱动。
驱动? 不同接口之间的数据(信号)转换程序。
JDBC的驱动:java接口和关系型数据库之间的信号转换程序。 不同的数据库就需要不同的转换程序。
java连接数据库的工作原理
对于程序员来说,只要关心java提供的操作数据的接口即可。
JDBC常用接口
DriverManager:这个类管理数据库驱动程序的列表,查看加载的驱动是否符合JAVA Driver API的规范。
Connection:与数据库中的所有的通信是通过唯一的连接对象。 一个连接。
Statement:把创建的SQL对象,转而存储到数据库当中。 发送sql。
ResultSet:它是一个迭代器,用于检索查询数据。 查询的结构。
JDBC的基本操作步骤
[0]准备,准备JDBC的驱动包。
驱动包是数据库开发商提供的,在java库中是没有的,需要我们下载,并且加入到我们的classpath中。
下载驱动:
https://mvnrepository.com/search
搜索mysql,根据自己的版本需求点开:进入详情页面之后,点击下载jar文件:
创建一个java项目,将驱动加入项目的classpath中:
说明: 所谓classpath就是JVM在启动的时候,加载类的路径。
之所以要将jar文件加入到classpath中,就是希望JVM在找驱动的时候能找到。
具体操作:
在项目的根目录下创建一个lib文件夹,将驱动的jar文件拷贝到lib中。
开始将jar文件加入到项目的classpath中:
找到你的驱动jar文件。
添加完成。
产生一个连接
public class Demo1 { public static void main(String[] args) throws ClassNotFoundException, SQLException { // 步骤1 : 加载驱动 // 参数是驱动类的列名,不同的数据库驱动类名不同。 // MySQL5.x和MySQL8.x驱动类名不同。 Class.forName("com.mysql.jdbc.Driver"); // 步骤2: 获取连接 // 参数1 : url // 参数2: 连接数据库的用户名 // 参数3: 连接数据库的密码 Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/books","root","root123"); System.out.println(con); } }
获取连接中的url说明: url->统一资源定位器 jdbc:mysql://127.0.0.1:3306/books jdbc:mysql: 这个是固定的前缀,不同的数据库前缀不同 3306 : MySQL数据库默认的服务监听端口。 127.0.0.1 : 是mysql所在的服务器的地址。如果是本机,可以使用localhost。 /books : 要连接的数据库的名字。
[1]加载驱动。
[2]获取连接。
[3]创建statement。
[4]执行sql语句。
[5]处理执行结果。
[6]关闭连接。
完整案例
public class Demo2 { private static final String DRIVER_CLASS="com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/books"; private static final String USERNAME = "root"; private static final String PASSWORD = "root123"; public static void main(String[] args) { // 将需要的对象申明在try语句块以外 Connection con = null; Statement st = null; ResultSet rs = null; try { //[1]加载驱动。 Class.forName(DRIVER_CLASS); //[2]获取连接。 con = DriverManager.getConnection(URL,USERNAME,PASSWORD); //[3]创建statement。 st = con.createStatement(); //[4]执行sql语句。 // 准备一个字符串,存储sql语句 String sql = "select * from g_book"; rs = st.executeQuery(sql); // 这里的rs对象就是我们查询的一张虚拟表 //[5]处理执行结果。 while(rs.next()){// 将结果集的数据逐行遍历 String isbn = rs.getString("isbn"); String title = rs.getString("title"); float cost = rs.getFloat("cost"); int categoryId = rs.getInt("category_Id"); System.out.println("isbn:"+isbn +",title:"+title+",cost:"+cost+",categoryId:"+categoryId); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { try { // [6]关闭连接。 if(rs!=null) { rs.close(); } if(st!=null) { st.close(); } if(con!=null) { con.close(); } } catch (SQLException e) { e.printStackTrace(); } } } }
说明:
// [1]加载驱动。 Class.forName("com.mysql.jdbc.Driver");
这里使用反射机制将驱动相关的类加载到内存中。
不同的数据库会有不同的驱动的类名。MySQL8的驱动类名不一样。“com.mysql.cj.jdbc.Driver”
// [2]获取连接。 Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/books","root","root123");
获取连接使用的是java提供的一个类DriverManager,DriverManager中有多个静态方法可以获取一个有效的连接。我们这里使用的方法需要传入三个参数。 三个参数分别是:
url : 连接数据库的地址。
前缀:jdcb:mysql://
服务器地址: localhost 当然也可以写IP地址。 127.0.0.1,
端口:3306。
数据库的名称: /books
username: 连接数据库的用户名。
password: 连接数据库的密码。
// [3]创建statement。 Statement st = con.createStatement();
通过Connection对象可以直接创建Statement。
Statement提供了大量的API用来执行的sql语句。
// [4]执行sql语句。 ResultSet rs = st.executeQuery("select * from g_book");
我们这里执行的查询操作,索引使用api: executeQuery(sql) 。查询执行结束之后会得到ResultSet对象。
如果是增删改,则使用API: executeUpdate(sql) 。返回数据库受影响的行数。(int)
// [5]处理执行结果。 while(rs.next()){ System.out.print(rs.getString("isbn")+"-"); System.out.print(rs.getString("title")+"-"); System.out.print(rs.getString("cost")+"-"); System.out.print(rs.getString("price")+"\n"); }
只要查询操作才有这一步。
我们可以简单的认为ResultSet就是一个虚拟表(迭代器),可以迭代处理查询返回的结果。
try { // [6]关闭连接。 if(rs!=null) { rs.close(); } if(st!=null) { st.close(); } if(con!=null) { con.close(); } } catch (SQLException e) { e.printStackTrace(); }
关闭连接。正常情况下 ResultSet,Statement,Connection都是需要关闭的。
JDBC完成添加操作
案例:通过JDBC给boys表添加一条数据
public class Demo2_Insert { // 连接数据库需要的常量 private static final String DRIVER_CLASS="com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/student"; private static final String USERNAME = "root"; private static final String PASSWORD = "root123"; public static void main(String[] args) { // 将需要的对象申明在try语句块以外 Connection con = null; Statement st = null; // ResultSet rs = null; 增删改都是没有查询结果,的所以不需要ResultSet try{ // 加载驱动 Class.forName(DRIVER_CLASS); // 获取链接 con = DriverManager.getConnection(URL,USERNAME,PASSWORD); // 获取Statement对象 st = con.createStatement();// 在内部创建了一个Statement接口实现类的对象,并且返回了这个对象。 // 准备sql语句 String sql = "insert into boys(id,boyname,usercp) values(6,'鸣人',50000)"; // 执行sql 增删改操作全部使用executeUpdate int result = st.executeUpdate(sql); // 这里result就是数据库受影响的行数 System.out.println(result); }catch (Exception e){ e.printStackTrace();// 将异常信息输出到控制台 }finally { try{ if(st!=null){ st.close(); } if(con !=null ){ con.close(); } }catch (Exception e){ e.printStackTrace(); } } } }
说明几个问题:
-
st使用什么方法执行sql语句。
在JDBC中,对数据库的操作只有两种。分别是修改和查询。所谓修改就是对数据库的数据产生了影响,比新增数据,修改数据,删除数据。 查询是对数据本身不产生任何影响的。
所以在执行增删改操作的时候统一使用 executeUpdate(sql) 返回的结果是数据库受影响的行数。
查询操作统一使用 executeQuery(sql) 返回的结果是查询的结果集(ResultSet对象)
JDBC完成修改操作
修改操作和添加操作的流程完全一致,仅仅修改修改sql语句即可。
public class Demo2_update { // 连接数据库需要的常量 private static final String DRIVER_CLASS="com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/student"; private static final String USERNAME = "root"; private static final String PASSWORD = "root123"; public static void main(String[] args) { // 将需要的对象申明在try语句块以外 Connection con = null; Statement st = null; // ResultSet rs = null; 增删改都是没有查询结果,的所以不需要ResultSet try{ // 加载驱动 Class.forName(DRIVER_CLASS); // 获取链接 con = DriverManager.getConnection(URL,USERNAME,PASSWORD); // 获取Statement对象 st = con.createStatement();// 在内部创建了一个Statement接口实现类的对象,并且返回了这个对象。 // 准备sql语句 String sql = "update boys set boyname = 'mingren' where id = 6"; // 执行sql 增删改操作全部使用executeUpdate int result = st.executeUpdate(sql); // 这里result就是数据库受影响的行数 System.out.println(result); }catch (Exception e){ e.printStackTrace();// 将异常信息输出到控制台 }finally { try{ if(st!=null){ st.close(); } if(con !=null ){ con.close(); } }catch (Exception e){ e.printStackTrace(); } } } }
JDBC完成删除操作
删除操作。。。。 程序就略了。在JDBC中增删改是同一个操作。
所有JDBC只有两个操作: update和query。
所以statement有两个重要的API: executeUpdate和executeQuery
JDBC查询操作-多行数据查询
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class Demo2_query { // 连接数据库需要的常量 private static final String DRIVER_CLASS="com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/student"; private static final String USERNAME = "root"; private static final String PASSWORD = "root123"; public static void main(String[] args) { // 将需要的对象申明在try语句块以外 Connection con = null; Statement st = null; ResultSet rs = null; //增删改都是没有查询结果,的所以不需要ResultSet try{ // 加载驱动 Class.forName(DRIVER_CLASS); // 获取链接 con = DriverManager.getConnection(URL,USERNAME,PASSWORD); // 获取Statement对象 st = con.createStatement();// 在内部创建了一个Statement接口实现类的对象,并且返回了这个对象。 // 准备sql语句 String sql = "select * from beauty"; // 执行sql 查询操作全部使用executeQuery(sql); rs = st.executeQuery(sql); // rs就是一个结果集 while(rs.next()){// 返回true说明这一行剥离成功 // 取出剥离出来的数据 rs.getXxxx(parm) xxx是对应的数据类型。 // parm可以是列的索引,索引从1开始计算 这个参数还可以是列名(不区分大小写) int id = rs.getInt(1); String name = rs.getString("name");// rs.getString(2); String sex = rs.getString("sex"); String birth = rs.getString("borndate"); String phone = rs.getString("phone"); int boyfriendId = rs.getInt("boyfriend_id"); System.out.println("id:"+id+",name:"+name+",sex:"+sex+",birth:"+birth+",phone:"+phone+",boyfriendId:"+boyfriendId); } }catch (Exception e){ e.printStackTrace();// 将异常信息输出到控制台 }finally { try{ if(rs!=null){ rs.close(); } if(st!=null){ st.close(); } if(con !=null ){ con.close(); } }catch (Exception e){ e.printStackTrace(); } } } }
看图理解结果集处理:
我们使用select * from beauty查询一张虚拟表,在ResultSet中:
会有一个指针指向每一行的上面,当我们执行rs.next的时候,指针会向下移动,移动成功就返回true,否则返回false。当到大最后一行之后,再next就返回false。
每移动一次,就剥离一行出来。我们可以通过rs.getXxx()方法获取这一行的所有的列的数据。
JDBC查询操作-单行数据查询
查询一条数据和查询多条数据本身是没有啥区别
public class Demo2_query_one { // 连接数据库需要的常量 private static final String DRIVER_CLASS="com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/student"; private static final String USERNAME = "root"; private static final String PASSWORD = "root123"; public static void main(String[] args) { // 将需要的对象申明在try语句块以外 Connection con = null; Statement st = null; ResultSet rs = null; //增删改都是没有查询结果,的所以不需要ResultSet try{ // 加载驱动 Class.forName(DRIVER_CLASS); // 获取链接 con = DriverManager.getConnection(URL,USERNAME,PASSWORD); // 获取Statement对象 st = con.createStatement();// 在内部创建了一个Statement接口实现类的对象,并且返回了这个对象。 // 准备sql语句 String sql = "select * from beauty where id = 1"; // 执行sql 查询操作全部使用executeQuery(sql); rs = st.executeQuery(sql); // rs就是一个结果集 if(rs.next()){// 返回true说明这一行剥离成功 // 取出剥离出来的数据 rs.getXxxx(parm) xxx是对应的数据类型。 // parm可以是列的索引,索引从1开始计算 这个参数还可以是列名(不区分大小写) int id = rs.getInt(1); String name = rs.getString("name");// rs.getString(2); String sex = rs.getString("sex"); String birth = rs.getString("borndate"); String phone = rs.getString("phone"); int boyfriendId = rs.getInt("boyfriend_id"); System.out.println("id:"+id+",name:"+name+",sex:"+sex+",birth:"+birth+",phone:"+phone+",boyfriendId:"+boyfriendId); } }catch (Exception e){ e.printStackTrace();// 将异常信息输出到控制台 }finally { try{ if(rs!=null){ rs.close(); } if(st!=null){ st.close(); } if(con !=null ){ con.close(); } }catch (Exception e){ e.printStackTrace(); } } } }
JDBC查询操作-单行单列数据查询
统计有多少美女:
public class Demo2_query_count { // 连接数据库需要的常量 private static final String DRIVER_CLASS="com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/student"; private static final String USERNAME = "root"; private static final String PASSWORD = "root123"; public static void main(String[] args) { // 将需要的对象申明在try语句块以外 Connection con = null; Statement st = null; ResultSet rs = null; //增删改都是没有查询结果,的所以不需要ResultSet try{ // 加载驱动 Class.forName(DRIVER_CLASS); // 获取链接 con = DriverManager.getConnection(URL,USERNAME,PASSWORD); // 获取Statement对象 st = con.createStatement();// 在内部创建了一个Statement接口实现类的对象,并且返回了这个对象。 // 准备sql语句 String sql = "select count(*) from beauty"; // 执行sql 查询操作全部使用executeQuery(sql); rs = st.executeQuery(sql); // rs就是一个结果集 if(rs.next()){// 返回true说明这一行剥离成功 int count = rs.getInt(1); // 直接根据索引取出 System.out.println("总共有"+count+"美女的信息"); } }catch (Exception e){ e.printStackTrace();// 将异常信息输出到控制台 }finally { try{ if(rs!=null){ rs.close(); } if(st!=null){ st.close(); } if(con !=null ){ con.close(); } }catch (Exception e){ e.printStackTrace(); } } } }
经过上面的代码浏览,你会发现,有一个固定的框架:
public class Demo2_query_count { // 连接数据库需要的常量 private static final String DRIVER_CLASS="com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/student"; private static final String USERNAME = "root"; private static final String PASSWORD = "root123"; public static void main(String[] args) { Connection con = null; Statement st = null; ResultSet rs = null; //增删改都是没有查询结果,的所以不需要ResultSet try{ Class.forName(DRIVER_CLASS); con = DriverManager.getConnection(URL,USERNAME,PASSWORD); st = con.createStatement(); //------------------------------------- // 准备sql语句 String sql = "select count(*) from beauty"; // 执行sql 查询操作全部使用executeQuery(sql); //rs = st.executeQuery(sql); // rs就是一个结果集 //if(rs.next()){// 返回true说明这一行剥离成功 // int count = rs.getInt(1); // 直接根据索引取出 // System.out.println("总共有"+count+"美女的信息"); //} //---------------------------------------- }catch (Exception e){ e.printStackTrace();// 将异常信息输出到控制台 }finally { try{ if(rs!=null){ rs.close(); } if(st!=null){ st.close(); } if(con !=null ){ con.close(); } }catch (Exception e){ e.printStackTrace(); } } } }
MySQL8.0的driver和url的写法:
URL写法: jdbc:mysql://localhost:3306/数据库名称?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true driver写法: com.mysql.cj.jdbc.Driver
常见的错误:
[1]数据库用户名和密码写错了。
[2]驱动找不到的错误
驱动类名字写错了或者驱动的jar文件没有添加到classpath下。
[3]url写错了
[4]SQL语句的拼写错误
表明写错,或者数据库名写错
sql语句的语法错误:
[5]使用rs.getXxxx(cname)的时候列名拼写错误
我们计算机使用的数据都是二进制,如果要将‘hello’存储到磁盘上,就需要将字符转换为二进制。使用一定的规则来将对应的字符转换为可以存储、传输的形式的方式就是编码。
编码规则有好多种。 ISO8859-1, 中文编码:GBK,GB2312,GB18030。 国际通用编码UTF-8。
乱码是怎么来?
输入的编码和输出的编码不一致导致的。
-
存储的时候使用的编码和读取的时候使用的编码不一致。
-
发送的时候使用的编码和接收的时候使用的编码不一致。
现在的问题:数据从APP到数据库就乱码了。
-
创建数据库的时候,设置数据库的编码为utf-8。
-
在使用JDBC连接数据数据库的时候,设置连接参数中的编码也为utf-8。
设置方式:在URL后面添加参数。
jdbc:mysql://127.0.0.1:3306/student?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
JDBC的封装
JDBC的使用方式。
DAO:
实现下面的接口:
public interface BookDAO {
/** * 根据传入的参数添加一本图书信息到图书表中 *
* @return 返回数据库受影响的行数
* */
public int save(String isbn,String title,float cost,float price,String pid,int categoryId);
/**
* 根据传入的参数修改一本图书信息
* tips:isbn是不能修改的,所以update 是根据isbn修改其他的列的值
* @return 返回数据库受影响的行数
* */
public int update(String isbn,String title,float cost,float price,String pid,int categoryId);
/**
* 根据isbn删除一本图书的信息 * @return 返回数据库受影响的行数
* */
public int delete(String isbn);
/** *
* 查询图书的总条数,返回总条数
* */
public int queryTotal();
/** *
* 根据isbn查询一本图书的信息,要求返回map,map结构如下 *
* {isbn:95279527,title:'一本测试图书',cost:25.5,price:35.5,pname:'胡说八道出版 社',cname:'童书'} *
* tips: 要连接查询的
* */
public Map queryByIsbn(String isbn);
/** *
* 根据标题查询图书信息. 注意要模糊查询 *
* sql = "select * from book where title like '%"+title+"%'; *
* 返回一个list,list中放的都是map,结构如下面的例子 */
public List<Map> queryByTitle(String title);
}
具体实现:
public class BookDAOImpl implements BookDAO {
// 连接数据库需要的常量
private final String DRIVER_CLASS="com.mysql.jdbc.Driver";
private final String URL = "jdbc:mysql://127.0.0.1:3306/books?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true";
private final String USERNAME = "root";
private final String PASSWORD = "root123";