本篇博客内容:
1 数据库(mysql)操作
在数据库中创建一张表,这里以用户表为例,如下图:table_name:user,您的table,怎么舒服怎么建:
还有jdbc驱动的jar包的引入我就略了,不要忘记导入这个jar包噢
2 创建类(User.java)
先封装一个用户类(User),当然你可以封装其他的类,在封装类的时候注意以下两点:
1. 类中的属性名要和数据库对应表的列名一致(一模一样拿过来就对了):是为了方便后面通过内省获取指定方法,名字不一样的话,找到地老天荒也找不到┗|`O′|┛ 嗷~~
2. 属性(成员)的数据类型最好是包装类型:通过内省获取的方法传参时用的是从数据库中拿出来的数据(放到结果集中了),你可以测试一下,这些数据是包装类型欧
也可以不实现Serializable接口,这个是实现数据库连接池时使用的,懒得删了~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| package com.myproject.beans; import java.io.Serializable;
public class User implements Serializable { private static final long serialVersionUID = 373910607014836778L; private Integer id; private String username; private String password; private Integer age; private String gendar;
public User() { }
public User(Integer id, String username, String password, Integer age, String gendar) { this.id = id; this.username = username; this.password = password; this.age = age; this.gendar = gendar; }
public Integer getId() { return id; }
public void setId(Integer 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 Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getGendar() { return gendar; }
public void setGendar(String gendar) { this.gendar = gendar; }
@Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", age=" + age + ", gendar='" + gendar + '\'' + '}'; } }
|
3 创建配置文件(db.properties)
主要是将连接数据库的几个变量封装一下,更换数据库信息的时候,我们只需要修改这个配置文件中的内容即可,对,一切为了方便,emm~懒创造了高效的代码:
1 2 3 4 5 6 7 8 9
| #驱动名称 driverClass=com.mysql.jdbc.Driver #数据库url url=jdbc:mysql:///mydatebase #当然上面的这句话就等价于:url=jdbc:mysql://localhost:3306/mydatabase #数据库用户名 user=root #数据库密码 password=root
|
本篇博客所有的精华都在这里了,来让我们一起来感受一下:
4.1 注册JDBC驱动
将注册驱动的实现代码置于静态代码块中,类被调用时首先被加载:
通过加载配置文件,完成JDBC的驱动注册,(悄咪咪的问一下,看到这里的你应该知道不同的数据库有不同的JDBC驱动不~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class DB_Tools{ private static String driverClass; private static String url; private static String user; private static String password;
static { try { InputStream inputStream = DB_Tools.class.getClassLoader().getResourceAsStream("db.properties"); Properties properties = new Properties(); properties.load(inputStream); driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); user = properties.getProperty("user"); password = properties.getProperty("password"); try { Class.forName(driverClass); System.out.println("注册驱动成功"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); System.out.println("注册驱动失败"); } } }
|
4.2 获取数据库连接
这个感觉没有什么好说的,就是常规操作嘛~
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class DB_Tools{
public static Connection getDBConnection() { try { return DriverManager.getConnection(url, user, password); } catch (SQLException e) { e.printStackTrace(); } return null; } }
|
4.3 断开连接释放资源
emmm,这个也是常规操作~
注意以下关闭的顺序就好了,这里我们用PreparedStatement的父类Statement(虽然我不是很喜欢这个接口),使代码更加灵活.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class DB_Tools{
public static void allClose(Connection connection, Statement statement, ResultSet resultSet) { try { if (resultSet != null) { resultSet.close(); } if (statement!= null) { statement.close(); } if (connection != null) { connection.close(); } System.out.println("执行结束"); } catch (SQLException e) { e.printStackTrace(); } } }
|
4.4 执行增删改查
代码中都有注释,我是仙女本仙没错了~看看下面的代码,增删改的操作返回的结果是一个int类型的数字:
操作成功 结果>0 返回受影响的行数,
操作失败 结果<0 返回的是一个负数,
还有一个点:这里用PreparedStatement,本仙不喜欢Statement,Statement会发生sql注入,嫌弃.PreparedStatement相对来说会做预处理,执行效率高还比较安全,可以举一个生动形象的例子:Statement是我眼里的渣男,而PreparedStatement就是那完美的男神!
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class DB_Tools{
public static int excumentDBUpdate(String sql, Object[] objects) { int updateResult = 0; Connection connection = null; PreparedStatement preparedStatement = null; try { connection = getDBConnection(); preparedStatement = connection.prepareStatement(sql); if (objects != null) { for (int i = 0; i < objects.length; i++) { preparedStatement.setObject(i + 1, objects[i]); } } updateResult = preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { allClose(connection, preparedStatement, null); } return updateResult; } }
|
4.5 (重点)查询数据
你也能看出来,前面的都太简单了,嗯哼不用写出来,谁都会的么那重点就来了:
下面的炫点有三个:
1.泛型的使用
2.反射的使用
> 3.内省的使用
上面使代码复用性更高
4.5.1 查询单条数据
思路:如代码中注释所示(我是有个仙女没错了,写代码还加注释~)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| public class DB_Tools{
public static T getObject(ResultSet resultSet, Class tClass) throws Exception { T object = tClass.newInstance(); ResultSetMetaData resultSetMetaData = resultSet.getMetaData(); for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) { String colName = resultSetMetaData.getColumnName(i + 1); PropertyDescriptor propertyDescriptor = new PropertyDescriptor(colName, tClass); if (propertyDescriptor != null) { Method method = propertyDescriptor.getWriteMethod(); method.invoke(object, resultSet.getObject(colName)); } } return object; }
public static T getSingleResult(String sql, Object[] objects, Class tClass) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; T object = null;
try { connection = getDBConnection(); preparedStatement = connection.prepareStatement(sql); if (objects != null) { for (int i = 0; i < objects.length; i++) { preparedStatement.setObject(i + 1, objects[i]); } } resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { object = getObject(resultSet, tClass); } } catch (Exception e) { e.printStackTrace(); } finally { allClose(connection, preparedStatement, resultSet); } return object; } }
|
4.5.2 查询多条数据
实现和前面的思路如出一辙,我们这里有个人的脚超级臭(我发现好像是我胖胖的同桌的jio…..),伴着阵阵吹向我的方向的微风,我快给熏牺牲了,怀疑人生….快速沾完这个代码撤!狗命重要!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class DB_Tools{
public static List getComplexResult(String sql, Object[] objects, Class tClass) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; List tList = new ArrayList();
try { connection = getDBConnection(); preparedStatement = connection.prepareStatement(sql); if (objects != null) { for (int i = 0; i < objects.length; i++) { preparedStatement.setObject(i + 1, objects[i]); } } resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { T object = getObject(resultSet, tClass); tList.add(object); } } catch (Exception e) { e.printStackTrace(); } finally { allClose(connection, preparedStatement, resultSet); } return tList; } }
|
本篇博客只是模拟了对JDBC增删改查超简易封装,和Apache提供的对JDBC进行简单封装的开源工具类库DBUtils还相差甚远,后面有时间我会写一篇关于DBUtils这个轻量级工具类的介绍,敬请期待.
感谢你看到了这里啊,
如果你有收获的话记得点赞呦
有问题可以留言,本仙看见了就会回复的
再见,祝您学习快乐,生活愉快~