JDBC如何连接不同类型数据库
作者:thulium_
这篇文章主要介绍了JDBC如何连接不同类型数据库问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
一、连接数据库
1. 连接mysql数据库
Connection conn = null; //数据库连接驱动名:针对不同的数据库,驱动名称不同,但是同一种类型的数据库改字符串相同 Class.forName("com.mysql.jdbc.Driver"); String url="JDBC:mysql://localhost:8080/testDB"; String user="test"; String password="test"; try { //1.加载驱动 Class.forName(driver ); //2.连接 conn = DriverManager.getConnection(url, user, password); System.out.println("连接数据库成功!"); PreparedStatement statement = null; //举个查询例子测试一下 //查询userinfo表的数据 statement = conn .prepareStatement("select * from userInfo"); ResultSet res = null; res = statement.executeQuery(); //当查询下一行有记录时:res.next()返回值为true,反之为false while (res.next()) { String TenantCode = res.getString("TenantCode"); String TenantName = res.getString("TenantName"); String Cloud = res.getString("Cloud"); System.out.println("学号:" + TenantCode + "姓名:" + TenantName + " 性别:" + Cloud); } } catch (Exception e) { e.printStackTrace(); System.out.println("连接数据库失败!"); }
2.连接sqlserver数据库
Connection conn = null; Class.forName("com.microsoft.JDBC.sqlserver.SQLServerDriver"); String url="JDBC:microsoft:sqlserver://localhost:1433;DatabaseName=testDb"; String user="test"; String password="test"; try { //1.加载驱动 Class.forName(driver ); //2.连接 conn = DriverManager.getConnection(url, user, password); System.out.println("连接数据库成功!"); } catch (Exception e) { e.printStackTrace(); System.out.println("连接数据库失败!"); }
3. 连接postgresql数据库
Connection conn = null; //数据库连接驱动名:针对不同的数据库,驱动名称不同,但是同一种类型的数据库改字符串相同 Class.forName("org.postgresql.Driver"); String url="JDBC:postgresql://localhost/testDb"; String user="test"; String password="test"; try { //1.加载驱动 Class.forName(driver ); //2.连接 conn = DriverManager.getConnection(url, user, password); System.out.println("连接数据库成功!"); } catch (Exception e) { e.printStackTrace(); System.out.println("连接数据库失败!"); }
4. 连接Oracle 数据库
Connection conn = null; Class.forName("oracle.JDBC.driver.OracleDriver"); String url="JDBC:oracle:thin:@localhost:1521:orcl"//orcl为Oracle数据库的SID String user="test"; String password="test"; try { //1.加载驱动 Class.forName(driver ); //2.连接 conn = DriverManager.getConnection(url, user, password); System.out.println("连接数据库成功!"); } catch (Exception e) { e.printStackTrace(); System.out.println("连接数据库失败!"); }
二、JDBCUtils(数据库常用操作工具类)
(1)获取数据库连接对象
(2)获取查询结果集
(3)将查询结果集转化为指定对象(使用者自行提供类参数,通过反射和转化)
(4)执行更新、删除、插入操作
(5)关闭数据库连接
package utils; import java.lang.reflect.Constructor; import java.lang.reflect.Method; 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; /** * 数据库常用操作工具类 * */ public final class JdbcUtils { // mysql8驱动 public static final String MYSQL8_DRIVER = "com.mysql.cj.jdbc.Driver"; /** * 结果集处理器 * */ public static interface ResultSetHandler<T> { /** * 将一个结果集转换成T类型 * * @param rs * @return */ T handle(ResultSet rs); } /** * 列处理器 * */ public static interface ColumnHandler<T> { /** * * @param method 根据列名自动匹配的方法名 * @param columnName 列名 * @param t 对象 * @param value 值 * @return 返回true,表示用户已处理完成,无需再处理,返回false,则代表用户不处理 */ boolean handleColumn(Method method, String columnName, T t, Object value); } /** * 内部类的目的,就是为了将结果集中的数据自动封装成对象 * */ public static class BeanListHandler<T> implements ResultSetHandler<List<T>> { private final Class<T> clazz; private ColumnHandler<T> columnHandler; public BeanListHandler(Class<T> clazz) { this.clazz = clazz; } public BeanListHandler(Class<T> clazz, ColumnHandler<T> columnHandler) { this.clazz = clazz; this.columnHandler = columnHandler; } @Override public List<T> handle(ResultSet rs) { // 返回值 List<T> list = new ArrayList<>(); // 存储所有列名(别名) List<String> columnNames = new ArrayList<>(); // 存储所有方法,键名是列名(别名),值即其对应的setter方法 Map<String, Method> methodMap = new HashMap<>(); // 获取所有列名 try { // 结果集元数据 ResultSetMetaData rsmd = rs.getMetaData(); // 返回查询结果集的列数 int count = rsmd.getColumnCount(); // 返回此类型的所有方法 Method[] methods = clazz.getDeclaredMethods(); for (int i = 0; i < count; i++) { // 获取列名,如果起别名,则获取别名 String columnName = rsmd.getColumnLabel(i + 1); columnNames.add(columnName);// 返回查询结果集的列名 // 组装出对象的方法名 String methodName = columnName.substring(0, 1).toUpperCase() + columnName.substring(1); methodName = "set" + methodName; for (Method me : methods) { if (me.getName().equals(methodName)) { methodMap.put(columnName, me);// 设置到map中 break; } } } // 准备工作已完成,将结果集中的数据转换成T类型的实例 if (rs != null) { // 获取无参的构造方法 Constructor<T> con = clazz.getDeclaredConstructor(); while (rs.next()) { T t = con.newInstance();// T类型的实例 for (int i = 0; i < count; i++) { String columnName = columnNames.get(i); // 从结果集中取出对应列的数据 Object value = rs.getObject(columnName); // 取出方法 Method method = methodMap.get(columnName); if (method != null) { if (columnHandler != null) { boolean done = columnHandler.handleColumn(method, columnName, t, value); if (!done) { // 通过反射给T类型的实例赋值 method.invoke(t, value); } } } } list.add(t); } } return list; } catch (Exception e) { e.printStackTrace(); } return null; } } /** * 获取数据库连接 * * @param url * @param user * @param password * @return */ public static final Connection getConnection(String driver, String url, String user, String password) { try { Class.forName(driver); return DriverManager.getConnection(url, user, password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } throw new RuntimeException("无法创建数据库连接"); } /** * 获取数据库连接 * * @param url * @param user * @param password * @return */ public static final Connection getConnection(String url, String user, String password) { return getConnection(MYSQL8_DRIVER, url, user, password); } /** * 执行查询操作,返回结果集 * * @param conn * @param sql * @param args * @return */ private static final ResultSet query(Connection conn, String sql, Object[] args) { try { PreparedStatement ps = conn.prepareStatement(sql); if (args != null) { // 给PreparedStatement实例设置参数 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } } return ps.executeQuery(); } catch (SQLException e) { e.printStackTrace(); } throw new RuntimeException("查询出现异常"); } /** * 返回对象的集合 * * @param <T> * @param conn * @param sql * @param args * @return */ public static final <T> T query(Connection conn, ResultSetHandler<T> handler, String sql, Object[] args) { ResultSet rs = query(conn, sql, args); return handler.handle(rs); } /** * 写操作 * * @return 返回受影响的行数 */ public static final int update(Connection conn, String sql, Object[] args) { try { PreparedStatement ps = conn.prepareStatement(sql); if (args != null) { // 给PreparedStatement实例设置参数 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } } return ps.executeUpdate(); } catch (SQLException e) { // e.printStackTrace(); } return -1; } /** * 关闭数据库连接 * * @param conn */ public static final void closeConnection(Connection conn) { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
三、自定义JDBCUtils
我采用的是:
- JDBCUtils来连接和关闭数据库相关资源。
- 再写一个类(BeanJDBCUtils)来进行数据库的基本操作。
- 最后写一个类来实现具体的操作。
1. JDBCUtils
/** * @author long * @date 2022/6/15 14:00 * @Description: 连接数据库的类 */ @SuppressWarnings("all") public class JDBCUtils { private static final String url; private static final String userName; private static final String password; private static final String driver; static { Properties properties = new Properties(); InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"); try { properties.load(is); url = properties.getProperty("url"); userName = properties.getProperty("userName"); password = properties.getProperty("password"); driver = properties.getProperty("driver"); //注册驱动 Class.forName(driver); } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description 获取数据库的连接 * @return */ public Connection getConnection() { try { return DriverManager.getConnection(url, userName, password); } catch (SQLException e) { throw new RuntimeException("无法连接到数据库\n"); } } /** * @Description 关闭连接 * @param connection */ public void close(Connection connection) { try { connection.close(); } catch (SQLException e) { throw new RuntimeException(e); } } /** * @Description 关闭连接 * @param connection */ public void close(Connection connection, ResultSet resultSet) { try { connection.close(); resultSet.close(); } catch (SQLException e) { throw new RuntimeException(e); } } }
2. BeanJDBCUtils
/** * @author long * @date 2022/6/15 15:23 * @Description: 对数据的操作的基本类 */ @SuppressWarnings("all") public class BeanJDBCUtils<T> extends JDBCUtils { private Connection connection; private PreparedStatement preparedStatement; private Class entityClass; /** * 构造方法,为了获取到泛型的对象的类,将其赋值给entityClass */ public BeanJDBCUtils() { //getClass() 获取Class对象,当前我们执行的是new FruitDAOImpl() , 创建的是FruitDAOImpl的实例 //那么子类构造方法内部首先会调用父类(BaseDAO)的无参构造方法 //因此此处的getClass()会被执行,但是getClass获取的是FruitDAOImpl的Class //所以getGenericSuperclass()获取到的是BaseJDBCUtils的Class //System.out.println("获取父类对象:" + clazz.getSuperclass()); Type genericType = getClass().getGenericSuperclass(); //ParameterizedType 参数化类型 Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); //获取到的<T>中的T的真实的类型 Type actualType = actualTypeArguments[0]; try { entityClass = Class.forName(actualType.getTypeName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * @param sql * @param args * @return * @Description: 查找数据库中多行数据 */ public List<T> query(String sql, Object... args) { List<T> list = new ArrayList<>(); connection = getConnection(); ResultSet resultSet = null; try { preparedStatement = connection.prepareStatement(sql); /*填充占位符*/ for (int i = 0; i < args.length; ++i) preparedStatement.setObject(i + 1, args[i]); preparedStatement.execute(); /*获取返回结果*/ resultSet = preparedStatement.getResultSet(); /*获取返回结果的数据*/ ResultSetMetaData metaData = resultSet.getMetaData(); /*获取数据的行数*/ int columnCount = metaData.getColumnCount(); while (resultSet.next()) { /*初始化泛型*/ T entity = (T) entityClass.newInstance(); Object object = new Object(); for (int i = 0; i < columnCount; ++i) { /*获取列名的别名,如果没有别名则直接获取列名*/ String columnLabel = metaData.getColumnLabel(i + 1); object = resultSet.getObject(i + 1); /*使用反射给泛型变量赋值*/ Field field = entity.getClass().getDeclaredField(columnLabel); field.setAccessible(true); field.set(entity, object); } list.add(entity); } return list; } catch (Exception e) { throw new RuntimeException(e); } finally { close(connection, resultSet); } } /** * * @param sql * @param clazz * @param args * @return * @Description: 查找数据库中单行数据 */ public T query(String sql, Class clazz, Object... args) { connection = getConnection(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < args.length; ++i) preparedStatement.setObject(i + 1, args[i]); resultSet = preparedStatement.executeQuery(); ResultSetMetaData metaData = resultSet.getMetaData(); int columnCount = metaData.getColumnCount(); T t = (T) entityClass.newInstance(); if (resultSet.next()) { Object object = new Object(); for (int i = 0; i < columnCount; i++) { String columnLabel = metaData.getColumnLabel(i + 1); Field field = t.getClass().getDeclaredField(columnLabel); field.setAccessible(true); object = resultSet.getObject(columnLabel); field.set(t, object); } } return t; } catch (Exception e) { throw new RuntimeException(e); } finally { close(connection, resultSet); } } /** * @param sql * @param args * @return 影响的行数 * @Description: 增删改 */ public Integer updata(String sql, Object... args) { connection = getConnection(); PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < args.length; ++i) preparedStatement.setObject(i + 1, args[i]); return preparedStatement.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } finally { close(connection); } } /** * @param sql * @param args * @param <E> * @return * @Description: 查找特定的值,并返回单一基本类型 */ public <E> E getElement(String sql, Object... args) { connection = getConnection(); ResultSet resultSet = null; try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) { for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i + 1, args[i]); } Object object = null; resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { object = resultSet.getObject(1); } return (E) object; } catch (SQLException e) { throw new RuntimeException(e); } finally { close(connection, resultSet); } } }
创建一个与数据库表t_fruit一一对应的Fruit类
import lombok.*; /** * @author long * @date 2022/6/15 14:58 * @Description: 与数据库中的t_fruit表一一对应的水果类 */ @ToString @Data @NoArgsConstructor @AllArgsConstructor @SuppressWarnings("all") public class Fruit { private Integer fid; private String fname; private Integer price; private Integer fcount; private String remark; public Fruit(String fname, Integer price, Integer fcount, String remark) { this.fname = fname; this.price = price; this.fcount = fcount; this.remark = remark; } }
创建一个接口(FruitDAO)来声明对改数据库的表中的操作的方法。
import java.util.List; public interface FruitDAO { /*获取所有水果信息*/ List<Fruit> getAllFruit(); /*添加水果信息*/ Integer addFruit(Fruit fruit); /*获取水果的种类的数量*/ Long getAllCount(); /*获取最大价格*/ Integer getMaxPrice(); /*获取最小价格*/ Integer getMinPrice(); Fruit getFruitById(Integer id); }
对上述接口(FruitDAO)的实现类(FruitDAOImpl)
/** * @author long * @date 2022/6/15 15:04 * @Description: 对数据库中t_fruit表的操作的类 */ public class FruitDAOImpl extends BeanJDBCUtils<Fruit> implements FruitDAO { @Override public List<Fruit> getAllFruit() { String sql = "select * from t_fruit"; return query(sql); } @Override public Integer addFruit(Fruit fruit) { String sql = "insert into t_fruit(fname,price,fcount,remark) values(?,?,?,?)"; return updata(sql, fruit.getFname(), fruit.getPrice(), fruit.getFcount(), fruit.getRemark()); } @Override public Long getAllCount() { String sql = "select count(*) from t_fruit"; return getElement(sql); } @Override public Integer getMaxPrice() { String sql = "select max(price) from t_fruit"; return getElement(sql); } @Override public Integer getMinPrice() { String sql = "select min(price) from t_fruit"; return getElement(sql); } @Override public Fruit getFruitById(Integer id) { String sql = "select * from t_fruit where fid = ?"; return query(sql, Fruit.class, id); } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。