二.JDBC知识点全面总结1:JDBC实战编写CRUD
1.JDBC重要接口?
①装载驱动接口
Driver接口:对接MySQL提供的Driver具体实现类 DriverManager类:封装Driver实例。
②连接
Connetion接口:获取和MySQL服务器的连接 获取connection实例的方式: driver.connect(); DriverManger.getConnection();
③执行SQL语句
Statement类(执行静态SQL语句并接受返回结果) Statement类:SQL语句无参数 PreparedStatement类继承Statement类:SQL语句有参数(防止sql注入) 执行方法 execute()运行无返回值 executeQuery()运行select语句有返回集 executeUpdate()运行Insert/delete/Update语句返回影响的行数
2.Driver和DriverManger的关系?
①对比
Driver是所有JDBC驱动类实现的接口 DriverMangement封装Driver
②使用
Driver创建驱动实例后直接获取连接 driver.connect() DriverMangement初始化(注册)Driver后直接获取连接 DriverMangement.getConnetion
③实战使用
Class.forName()加载类而且执行静态代码快。数据库驱动(Driver)中有静态代码块即注册驱动到DriverMangement 故实战可以使用DriverMangement,在加载驱动类后直接获取连接。
3.JAVA与数据库连接
①获取连接注意事项
properties的编写,注意直接连接的具体数据库 class.forName在加载驱动类时执行类中静态代码,已经从DriverMangement中注册(初始化)
②获取连接代码
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:13306/mytest?useUnicode=true&characterEncoding=utf8&useSSL=false
user=root
password=abc123
< dependency> < groupId> mysql</ groupId> < artifactId> mysql-connector-java</ artifactId> < version> 5.1.37</ version> </ dependency>
package com. likejin ; import java. io. InputStream ;
import java. sql. Connection ;
import java. sql. DriverManager ;
import java. sql. PreparedStatement ;
import java. sql. Statement ;
import java. util. Properties ; public class MyTest2 { public static void main ( String [ ] args) throws Exception { InputStream resourceAsStream = MyTest2 . class . getClassLoader ( ) . getResourceAsStream ( "jdbc.properties" ) ; Properties properties = new Properties ( ) ; properties. load ( resourceAsStream) ; String driverClass = properties. getProperty ( "driverClass" ) ; String url = properties. getProperty ( "url" ) ; String user = properties. getProperty ( "user" ) ; String password = properties. getProperty ( "password" ) ; Class . forName ( driverClass) ; Connection connection = DriverManager . getConnection ( url, user, password) ; }
}
4.JAVA中使用statement来执行sql语句时,拼接字符串的sql注入问题?
①statement
是通过获取连接之后利用其来执行sql语句 原理:字符串拼接(由于数据必须通过’'来包含)
②sql注入问题
package com. likejin ; import com. likejin. util. Utils ; import java. sql. Connection ;
import java. sql. ResultSet ;
import java. sql. Statement ;
import java. util. Scanner ; public class MyTest3 { public static void main ( String [ ] args) throws Exception { Connection conn = Utils . getconn ( ) ; Statement statement = conn. createStatement ( ) ; Scanner scanner = new Scanner ( System . in) ; System . out. println ( "请输入ID" ) ; String id = scanner. nextLine ( ) ; System . out. println ( "请输入年龄" ) ; String age = scanner. nextLine ( ) ; String sql = "select * from student where id = '" + id + "' and age = '" + age+ "'" ; System . out. println ( sql) ; ResultSet resultSet = statement. executeQuery ( sql) ; if ( resultSet. next ( ) ) { System . out. println ( "您找的学生在这个班级" ) ; } else { System . out. println ( "您找的学生不在这个班级" ) ; } }
}
数据表 正常情况下 sql注入问题加上单引号 sql注入 不加单引号
5.使用preparedstatement进行增删改查
①preparedstatement的方法
setObject 来填充占位符 execute() 来执行增删改,返回boolean类型是否成功 executeQuery()来执行查,返回ResultSet结果集
②ResultSet的方法
next() 判断下一个是否存在,存在指正下移,返回true,不存在指正不动,返回false getObject(i) 参数为行数据的第几列,返回的是某一行数据的某一列的具体数值 getMetaData()获取到ResultSetMetaData类型,该类型有方法: getColumnCount()返回具体列数 getColumnName(i)返回某一列的名称
②注意事项
注意数据库中列从第一列开始,而JAVA数据一般从0开始,故计算时注意+1。 注意sql注入时参数也是从第一个开始的。 注意封装类时需要设置属性为public,否则无法利用反射初始化值。 注意如果要编写未知数据的查找(封装为该类的list),需要知道数据的类型: 可以用泛型方法来传入封装的数据类型 Class <T> clazz T t
②代码
package com. likejin. util ; import com. likejin. MyTest2 ;
import com. likejin. Student ; import java. io. InputStream ;
import java. lang. reflect. Field ;
import java. sql. * ;
import java. util. ArrayList ;
import java. util. List ;
import java. util. Properties ; public class Utils { public static Connection getconn ( ) throws Exception { InputStream resourceAsStream = MyTest2 . class . getClassLoader ( ) . getResourceAsStream ( "jdbc.properties" ) ; Properties properties = new Properties ( ) ; properties. load ( resourceAsStream) ; String driverClass = properties. getProperty ( "driverClass" ) ; String url = properties. getProperty ( "url" ) ; String user = properties. getProperty ( "user" ) ; String password = properties. getProperty ( "password" ) ; Class . forName ( driverClass) ; Connection connection = DriverManager . getConnection ( url, user, password) ; return connection; } public static boolean updateData ( String sql, Object . . . args) throws Exception { Connection conn = getconn ( ) ; PreparedStatement preparedStatement = conn. prepareStatement ( sql) ; for ( int i = 0 ; i < args. length; i++ ) { preparedStatement. setObject ( i + 1 , args[ i] ) ; } boolean execute = preparedStatement. execute ( ) ; preparedStatement. close ( ) ; conn. close ( ) ; return execute; } public static List selectData ( String sql, Object . . . args) throws Exception { Connection conn = getconn ( ) ; PreparedStatement preparedStatement = conn. prepareStatement ( sql) ; for ( int i = 0 ; i < args. length; i++ ) { preparedStatement. setObject ( i + 1 , args[ i] ) ; } ResultSet resultSet = preparedStatement. executeQuery ( ) ; ArrayList < Student > students = new ArrayList < > ( ) ; int i = 0 ; while ( resultSet. next ( ) ) { Student student = new Student ( ) ; student. setId ( resultSet. getInt ( 1 ) ) ; student. setAge ( resultSet. getInt ( 2 ) ) ; student. setGrade ( resultSet. getInt ( 3 ) ) ; i = i + 1 ; students. add ( student) ; } return students; } public static < T > List < T > selectData ( Class < T > clazz, String sql, Object . . . args) throws Exception { Connection conn = getconn ( ) ; PreparedStatement preparedStatement = conn. prepareStatement ( sql) ; for ( int i = 0 ; i < args. length; i++ ) { preparedStatement. setObject ( i + 1 , args[ i] ) ; } ArrayList < T > ts = new ArrayList < > ( ) ; ResultSet resultSet = preparedStatement. executeQuery ( ) ; ResultSetMetaData metaData = resultSet. getMetaData ( ) ; int columnCount = metaData. getColumnCount ( ) ; while ( resultSet. next ( ) ) { T t = clazz. newInstance ( ) ; for ( int i = 0 ; i< columnCount; i++ ) { Field dd = clazz. getDeclaredField ( metaData. getColumnName ( i+ 1 ) ) ; dd. set ( t, resultSet. getObject ( i+ 1 ) ) ; } ts. add ( t) ; } return ts; }
}
6.自定义通用查询方法
①缺点
运行时类和类类型不同,无法在方法中就强转为需要的类类型。 stuent.getClass() 或者Student.class都和 Student不同 故如果想获得类类型,就需要运用泛型。 举例说明 如果想在传入方法中获取该类的类型如何获取? 利用泛型 T t或者 Class<T> clazz都可获取类型为T 利用Object o 获取不到类类型,最多获取运行时类的实例,故需要在获取方法的返回值后手动进行强转。 对象获取到类类型的数据是什么?为什么不能强转? 即最多获取到类类型字符串 String typeName = o1.getClass().getTypeName();由于编译的限制,无法去利用字符串强转对象。
②代码
public static List selectData5 ( Object o, String sql, Object . . . args) throws Exception { InputStream resourceAsStream = Utils . class . getClassLoader ( ) . getResourceAsStream ( "jdbc.properties" ) ; Properties properties = new Properties ( ) ; properties. load ( resourceAsStream) ; final String url = properties. getProperty ( "url" ) ; String user = properties. getProperty ( "user" ) ; String password = properties. getProperty ( "password" ) ; Class . forName ( properties. getProperty ( "driverClass" ) ) ; Connection connection = DriverManager . getConnection ( url, user, password) ; PreparedStatement preparedStatement = connection. prepareStatement ( sql) ; for ( int i = 0 ; i< args. length; i++ ) { preparedStatement. setObject ( i+ 1 , args[ i] ) ; } ResultSet resultSet = preparedStatement. executeQuery ( ) ; ResultSetMetaData metaData = resultSet. getMetaData ( ) ; ArrayList arrayList = new ArrayList ( ) ; int columnCount = metaData. getColumnCount ( ) ; while ( resultSet. next ( ) ) { Object o1 = o. getClass ( ) . newInstance ( ) ; for ( int i = 0 ; i< columnCount; i++ ) { String columnName = metaData. getColumnName ( i + 1 ) ; Field field = o1. getClass ( ) . getField ( columnName) ; field. set ( o1, resultSet. getObject ( i+ 1 ) ) ; } arrayList. add ( o1) ; } return arrayList; } public static void main ( String [ ] args) throws Exception { String sql = "select * from student where id<?" ; List students1 = null ; List list = selectData5 ( new Student ( ) , sql, 10 ) ; Iterator iterator = list. iterator ( ) ; while ( iterator. hasNext ( ) ) { System . out. println ( ( Student ) iterator. next ( ) ) ; } }
未更新