用jdbc连接数据库并简单执行SQL语句
一:版本一.这种存在一个问题就是每执行一次操作都会创建一次Connection链接和且释放一次链接
1:创建pojo对象(OR映射,一个pojo类对应一张数据库表)
- package com.yinfu.dao;
- public class Employee {
- private int id;
- private String name;
- private String password;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- @Override
- public String toString() {
- return "Employee [id=" + id + ", name=" + name + ", password=" + password + "]";
- }
- public Employee(int id, String name, String password) {
- super();
- this.id = id;
- this.name = name;
- this.password = password;
- }
- public Employee() {
- super();
- }
- }
pojo对象
2:创建数据库连接用的数据文件,用于外界读取数据(properties文件):
driver=com.mysql.jdbc.Driver jdbcUrl=jdbc:mysql://localhost:3306/test user=root password=song12345
3:创建数据库连接和关闭连接的工具类(被重复使用的方法可以写在工具类中):
- package com.yinfu.utils;
- import java.io.IOException;
- import java.io.InputStream;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.Properties;
- /**
- * JDBC的工具类,封装了jdbc的一些方法
- * @author lusong
- *
- */
- public class JDBCUtils {
- //关闭jdbc的链接
- /**
- * 关闭statement和connection
- * @param ps
- * @param conn
- */
- public static void release(PreparedStatement ps, Connection conn){
- try {
- if(ps != null){
- ps.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }finally{
- try {
- if(conn != null){
- conn.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- public static void release(ResultSet result,PreparedStatement ps, Connection conn){
- try {
- if(result != null){
- result.close();
- }
- } catch (SQLException e1) {
- e1.printStackTrace();
- }finally{
- try {
- if(ps != null){
- ps.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }finally{
- try {
- if(conn != null){
- conn.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
- //获取jdbc的链接
- /**
- * 用于创建jdbc链接的工具类对象
- * @return
- */
- public static Connection getConnetions() {
- Connection conn = null;
- String driverClass = null;
- String jdbcUrl = null;
- String user = null;
- String password = null;
- try {
- //读取配置文件中的配置
- InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
- Properties properties = new Properties();
- properties.load(is);
- driverClass = properties.getProperty("driver");
- jdbcUrl = properties.getProperty("jdbcUrl");
- user = properties.getProperty("user");
- password = properties.getProperty("password");
- //注册驱动程序
- Class.forName(driverClass);
- //实际应该这样写(由于对应的应用程序中有一个对应的静态代码块,自动回将驱动的类对象进行驱动加载)
- //DriverManager.registerDriver((Driver) Class.forName(driverClass).newInstance());
- conn = DriverManager.getConnection(jdbcUrl,user,password);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return conn;
- }
- }
4:用Junit测试实现的JDBC实现数据库的增删改查操作:
- package com.yinfu.test;
- import java.io.IOException;
- import java.io.InputStream;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Properties;
- import org.junit.Test;
- import com.yinfu.dao.Employee;
- import com.yinfu.utils.JDBCUtils;
- public class JDBCTest {
- @Test
- public void testUpdate(){
- //曾
- String sql = "insert into employee (Id,Name,Password) values (1,'wangba',131)";
- //删
- //String sql = "delete from employee where id = 1";
- //改
- //String sql = "update employee set name = 'fuck' where id = 2";
- //查
- String sqlQuery = "select * from employee";
- update(sql);
- testQueryObject(sqlQuery);
- }
- public void testQueryObject(String sql){
- Employee employee = null;
- List<Employee> list = new ArrayList();
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet result = null;
- try {
- //创建连接
- conn = JDBCUtils.getConnetions();
- //创建prepareStatement对象,用于执行SQL
- ps = conn.prepareStatement(sql);
- //获取查询结果集
- result = ps.executeQuery();
- while(result.next()){
- employee = new Employee(result.getInt(1),result.getString(2),result.getString(3));
- list.add(employee);
- }
- System.out.println(list);
- } catch (Exception e) {
- e.printStackTrace();
- }finally{
- JDBCUtils.release(result, ps, conn);
- }
- }
- public void update(String sql){
- Connection conn = null;
- PreparedStatement ps = null;
- try {
- //创建数据库连接
- conn = JDBCUtils.getConnetions();
- //创建执行SQL的prepareStatement对象
- ps = conn.prepareStatement(sql);
- //用于增删改操作
- int result = ps.executeUpdate();
- System.out.println(result);
- } catch (Exception e) {
- System.out.println("出现异常1="+e.toString());
- }finally{
- JDBCUtils.release(ps, conn);
- }
- }
- }
Statement 和PrepareStatement的区别:
首先是执行SQL的方法:
statement:
Class.forName(jdbcDriver);
Connection conn = DriverManager.getConnection(jdbcUrl,userName,password);
String sql = "insert into employee () values ('','','')"
Statement statement = conn.createStatement();
statement.executeUpdate(sql);
其中的SQL语句中若有要动态输入的数据时,需要用字符串拼接SQL,难以维护容易出错。
prepareStatement:
Class.forName(jdbcDriver);
Connection conn = DriverManager.getConnection(jdbcUrl,userName,password);
String sql = "insert into employee () values ('','','')"
PrepareStatement ps = conn.prepareStatement(sql);
statement.executeUpdate();
其中的SQL语句中要是有动态输入的数据时,可以用占位'?'符来代替:
String sql = "insert into employee () values (?,?,?)";
然后用prepareStatement接口中的方法来动态赋值:
ps.setXXX(int paramIndex ,Object value);//参数含义:占位符对应的索引值,该索引值对应的参数值;
2:(利用反射工具类)升级版查询:利用反射和JDBC元数据编写通用的查询单条记录方法(ResultSetMetaData是结果集的元数据对象):
1:创建反射工具类:
- package com.yinfu.utils;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- /**
- * 反射的 Utils 函数集合 提供访问私有变量, 获取泛型类型 Class, 提取集合中元素属性等 Utils 函数
- *
- * @author Administrator
- *
- */
- public class ReflectionUtils {
- /**
- * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型 如: public EmployeeDao extends
- * BaseDao<Employee, String>
- *
- * @param clazz
- * @param index
- * @return
- */
- @SuppressWarnings("unchecked")
- public static Class getSuperClassGenricType(Class clazz, int index) {
- Type genType = clazz.getGenericSuperclass();
- if (!(genType instanceof ParameterizedType)) {
- return Object.class;
- }
- Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
- if (index >= params.length || index < 0) {
- return Object.class;
- }
- if (!(params[index] instanceof Class)) {
- return Object.class;
- }
- return (Class) params[index];
- }
- /**
- * 通过反射, 获得 Class 定义中声明的父类的泛型参数类型 如: public EmployeeDao extends
- * BaseDao<Employee, String>
- *
- * @param <T>
- * @param clazz
- * @return
- */
- @SuppressWarnings("unchecked")
- public static <T> Class<T> getSuperGenericType(Class clazz) {
- return getSuperClassGenricType(clazz, 0);
- }
- /**
- * 循环向上转型, 获取对象的 DeclaredMethod
- *
- * @param object
- * @param methodName
- * @param parameterTypes
- * @return
- */
- public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes) {
- for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
- .getSuperclass()) {
- try {
- // superClass.getMethod(methodName, parameterTypes);
- return superClass.getDeclaredMethod(methodName, parameterTypes);
- } catch (NoSuchMethodException e) {
- // Method 不在当前类定义, 继续向上转型
- }
- // ..
- }
- return null;
- }
- /**
- * 使 filed 变为可访问
- *
- * @param field
- */
- public static void makeAccessible(Field field) {
- if (!Modifier.isPublic(field.getModifiers())) {
- field.setAccessible(true);
- }
- }
- /**
- * 循环向上转型, 获取对象的 DeclaredField
- *
- * @param object
- * @param filedName
- * @return
- */
- public static Field getDeclaredField(Object object, String filedName) {
- for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
- .getSuperclass()) {
- try {
- return superClass.getDeclaredField(filedName);
- } catch (NoSuchFieldException e) {
- // Field 不在当前类定义, 继续向上转型
- }
- }
- return null;
- }
- /**
- * 直接调用对象方法, 而忽略修饰符(private, protected)
- *
- * @param object
- * @param methodName
- * @param parameterTypes
- * @param parameters
- * @return
- * @throws InvocationTargetException
- * @throws IllegalArgumentException
- */
- public static Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes, Object[] parameters)
- throws InvocationTargetException {
- Method method = getDeclaredMethod(object, methodName, parameterTypes);
- if (method == null) {
- throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
- }
- method.setAccessible(true);
- try {
- return method.invoke(object, parameters);
- } catch (IllegalAccessException e) {
- System.out.println("不可能抛出的异常");
- }
- return null;
- }
- /**
- * 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter
- *
- * @param object
- * @param fieldName
- * @param value
- */
- public static void setFieldValue(Object object, String fieldName, Object value) {
- Field field = getDeclaredField(object, fieldName);
- if (field == null)
- throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
- makeAccessible(field);
- try {
- field.set(object, value);
- } catch (IllegalAccessException e) {
- System.out.println("不可能抛出的异常");
- }
- }
- /**
- * 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
- *
- * @param object
- * @param fieldName
- * @return
- */
- public static Object getFieldValue(Object object, String fieldName) {
- Field field = getDeclaredField(object, fieldName);
- if (field == null)
- throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
- makeAccessible(field);
- Object result = null;
- try {
- result = field.get(object);
- } catch (IllegalAccessException e) {
- System.out.println("不可能抛出的异常");
- }
- return result;
- }
- }
反射工具类
2:编写通用查询:
- package com.yinfu.test;
- import java.io.IOException;
- import java.io.InputStream;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.ResultSetMetaData;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Properties;
- import org.junit.Test;
- import com.yinfu.dao.Employee;
- import com.yinfu.utils.JDBCUtils;
- import com.yinfu.utils.ReflectionUtils;
- public class JDBCTest {
- @Test
- public void testUpdate(){
- //查
- String sqlQuery = "select id, name, password from employee where name = ?";
- Object employee = testQueryObject(Employee.class,sqlQuery,"zhangsan");
- System.out.println("利用反射="+employee);
- }
- public <T> T testQueryObject(Class<T> clazz, String sql, Object ... args){
- T object = null;
- Map<String, Object> map = new HashMap<String, Object>();
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet resultSet = null;
- try {
- //创建连接
- conn = JDBCUtils.getConnetions();
- //创建prepareStatement对象,用于执行SQL
- ps = conn.prepareStatement(sql);
- //将参数赋值到sql的所需参数中
- for(int i = 0 ; i < args.length ; i++){
- ps.setObject(i+1, args[i]);
- }
- //一:根据SQL语句和传入的参数得到结果集,此结果集中全部是纯数据值,不带列名;
- resultSet = ps.executeQuery();
- //二:利用ResultSet对象得到ResultSetMetaData对象jdbc的元数据,根据此对象可以知道SQL语句查询了哪些列,以及列的别名是什么(具体参考JDBC的API进行学习)
- ResultSetMetaData rsmd = resultSet.getMetaData();
- while(resultSet.next()){
- //把列名的别名和列值分别取出来放到map中作为键值出现(resultSet和rsmd结合得到的就是一个表,和数据库表一样),由ResultSetMetaData得到每一列的别名, //由ResultSet 得到对应的值
- for(int i=0;i<rsmd.getColumnCount();i++){
- String columnLabel = rsmd.getColumnLabel(i+1);
- Object columnValue = resultSet.getObject(columnLabel);
- map.put(columnLabel, columnValue);
- }
- }
- //利用反射创建class对应的对象
- object = (T) clazz.newInstance();
- //遍历map对象,用反射填充对象属性值
- for(Map.Entry<String, Object> entry : map.entrySet()){
- String fieldName = entry.getKey();
- Object fieldValue = entry.getValue();
- //利用反射工具類(属性名对应map的key值,属性名对应map的value值)
- ReflectionUtils.setFieldValue(object, fieldName, fieldValue);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }finally{
- JDBCUtils.release(resultSet, ps, conn);
- }
- return object;
- }
- }
3:利用BeanUtils工具类实现查询多条记录(添加commons-beanutils.jar和commons-logging.jar):
- package com.yinfu.test;
- import java.io.IOException;
- import java.io.InputStream;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.ResultSetMetaData;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Properties;
- import org.apache.commons.beanutils.BeanUtils;
- import org.junit.Test;
- import com.yinfu.dao.Employee;
- import com.yinfu.utils.JDBCUtils;
- import com.yinfu.utils.ReflectionUtils;
- public class JDBCTest {
- @Test
- public void testUpdate(){
- //查多条
- String sqlQueryList = "select id, name, password from employee";
- List<Employee> testQueryList = testQueryList(Employee.class,sqlQueryList);
- System.out.println("查询多条:"+testQueryList);
- }
- //查询多条记录
- public <T> List<T> testQueryList(Class<T> clazz, String sql, Object ...args ){
- //用于接收返回值
- T object = null;
- List<T> list = new ArrayList<>();
- Connection conn = null;
- PreparedStatement rs = null;
- ResultSet resultSet = null;
- try {
- //获取数据库连接
- conn = JDBCUtils.getConnetions();
- rs = conn.prepareStatement(sql);
- //填充占位符
- for(int i = 0; i < args.length; i++){
- rs.setObject(i+1, args[i]);
- }
- //获取结果集
- resultSet = rs.executeQuery();
- //1:准备一个List<Map<String, Object>>集合,其中key为列名,value为列值,每一个map对应一条记录
- List<Map<String, Object>> listMap = new ArrayList<>();
- //2:得到jdbc的元数据
- ResultSetMetaData rsmd = rs.getMetaData();
- while(resultSet.next()){
- Map<String, Object> map = new HashMap<>();
- for(int i = 0; i < rsmd.getColumnCount(); i++){
- //游标是从1开始的
- String columnLabel = rsmd.getColumnLabel(i+1);
- Object columnValue = resultSet.getObject(columnLabel);
- map.put(columnLabel, columnValue);
- }
- //3:把一条记录map放入到listMap中
- listMap.add(map);
- }
- /*//上面一段代码可以这样写
- List<String> labelList = getColumnLabels(resultSet);
- while(resultSet.next()){
- Map<String, Object> map = new HashMap<>();
- for(String columnLabel : labelList){
- Object columnValue = resultSet.getObject(columnLabel);
- map.put(columnLabel, columnValue);
- }
- //3:把一条记录map放入到listMap中
- listMap.add(map);
- }*/
- //4:遍历listMap集合,把其中的每一个map都转换成对应的Class对象,并放到list中进行返回
- if(listMap.size()>0){
- for(Map<String, Object> mapObj : listMap){
- //有记录就通过反射得到对应的类对象
- object = clazz.newInstance();
- for(Map.Entry<String, Object> entry : mapObj.entrySet()){
- String propertyName = entry.getKey();
- Object propertyValue = entry.getValue();
- //利用工具类beanutils进行实体类转换
- BeanUtils.setProperty(object, propertyName, propertyValue);
- }
- list.add(object);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return list;
- }
- private List<String> getColumnLabels(ResultSet resultSet) throws SQLException{
- ResultSetMetaData rsmd = resultSet.getMetaData();
- List<String> list = new ArrayList<>();
- for(int i = 0; i<rsmd.getColumnCount(); i++){
- list.add(rsmd.getColumnLabel(i+1));
- }
- return list;
- }
- }
查询多条记录
4:可以用获取PrepareStatement的另一个重载方法得到,然后再用此对象的getGeneratedKeys()方法得到插入的数据时自动生成的ID的结果集,此结果集就一列,列名为:GENERATED_K。
用jdbc连接数据库并简单执行SQL语句的更多相关文章
- JDBC进阶之PreparedStatement执行SQL语句(MySQL)
一.什么是PreparedStatement 参阅Java API文档,我们可以知道,PreparedStatement是Statement的子接口(如图所示),表示预编译的 SQ ...
- JDBC连接MYSQL,批量执行SQL语句或在执行一个SQL语句之前执行一个SQL语句
conn = MysqlJdbcUtils.getConnection(); Statement ps=conn.createStatement(); ps.addBatch("trunca ...
- BIML 101 - ETL数据清洗 系列 - BIML 快速入门教程 - 连接数据库执行SQL语句
BIML 101 - BIML 快速入门教程 第一节 连接数据库执行SQL语句 本小节将用BIML建一个简单的可以执行的包. 新建一个biml文件,贴入下面的代码 1 <Biml xmlns=& ...
- JDBC详解系列(四)之建立Stament和执行SQL语句
建立Stament 在获得连接之后,我们就可以跟数据库进行交互了. 在JDBC中,我们发送SQL语句到数据库这些操作时通过Stament,Preparement,CallableStateme ...
- JDBC中执行SQL语句的方式
一.执行DDL.DML语句 DDL.DML分别表示数据库定义语言.数据库操纵语言,操控这两种语言应该使用Statement对象的executeUpdate方法. 代码如下: public static ...
- 10.1(java学习笔记)JDBC基本操作(连接,执行SQL语句,获取结果集)
一.JDBC JDBC的全称是java database connection java数据库连接. 在java中需要对数据库进行一系列的操作,这时就需要使用JDBC. sun公司制定了关于数据库操作 ...
- JDBC课程2--实现Statement(用于执行SQL语句)--使用自定义的JDBCTools的工具类静态方法,包括insert/update/delete三合一
/**JDBC课程2--实现Statement(用于执行SQL语句) * 1.Statement :用于执行SQL语句的对象: * 1): 通过Connection 的createStatement( ...
- JDBC第一篇--【介绍JDBC、使用JDBC连接数据库、简单的工具类】
1.什么是JDBC JDBC全称为:Java Data Base Connectivity,它是可以执行SQL语句的Java API 2.为什么我们要用JDBC 市面上有非常多的数据库,本来我们是需要 ...
- JDBC【介绍JDBC、使用JDBC连接数据库、简单的工具类】
1.什么是JDBC JDBC全称为:Java Data Base Connectivity,它是可以执行SQL语句的Java API 2.为什么我们要用JDBC 市面上有非常多的数据库,本来我们是需要 ...
随机推荐
- [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 629 Solved: 371[Submit][Status ...
- Spring Boot应用的启动和停止(Spring Boot应用通过start命令启动)
Spring Boot,作为Spring框架对“约定优先于配置(Convention Over Configuration)”理念的最佳实践的产物,它能帮助我们很快捷的创建出独立运行.产品级别的基于S ...
- Java 等额本金等额本息工具类
原文:http://www.open-open.com/code/view/1449034309983 等额本息: /** * Description:等额本息工具类 * Copyright: Cop ...
- DELPHI跨平台的临界替代者
在WINDOWS里面使用临界来保护多线程需要访问的共享对象,现在,DELPHI有了新的跨平台临界保护者--System.TMonitor 代码演示如下: FConnections := TObject ...
- php monolog 的写日志到unix domain socket 测试终于成功
在另外一个客户端执行 php s.php后, 通过nc -lU /tmp/tg.sck 建立的unix domain socket 有接收到消息. <?php require 'vendor/a ...
- react 组件之间传值
谈及React时,就会想到一个很重要的思想,就是组件化思想.它将可以重用的部分进行组件化开发,形成一个个相对独立的组件,那么组件化后,你也会提出些疑问,组件与组件之间,将怎样进行信息的传递呢?下面来介 ...
- MySQL 当记录不存在时插入,当记录存在时更新
第一种: 示例一:插入多条记录 假设有一个主键为 client_id 的 clients 表,可以使用下面的语句: INSERT INTO clients (client_id,client_name ...
- java-组合优于继承
组合和继承.都能实现对类的扩展. 差别例如以下表所看到的 组合 继承 has-a关系 is-a关系 执行期决定 编译期决定 不破坏封装,总体和局部松耦合 破坏封装,子类依赖父类 支持扩展,任意添加组合 ...
- C++ 虚函数与纯虚函数 浅析
[摘要] 在虚函数与纯虚函数的学习中.要求理解虚函数与纯虚函数的定义,了解虚函数与纯虚函数在实例化上的差异.掌握两者在实现上的必要性.熟悉纯虚函数在子类与孙类的函数类型.本文即针对上述问题展开阐述. ...
- python itertools
1 product 1.1 一个generator函数 因此它的返回值是一个iterator,可以用for遍历. 1.2 计算product的参数分类 1.2.1 dict和list 只用了dict的 ...