创建一个项目,导入所需要的依赖包
这两个包分别是mysql的数据库驱动和c3p0数据库连接池
<dependencies> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.2.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> </dependencies>
接下来编写c3p0的配置文件(c3p0-config.xml)
<c3p0-config> <default-config> <!-- 必要参数 --> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/books?useSSL=false&serverTimezone=UTC</property> <property name="user">root</property> <property name="password">root</property> <!-- 下面不是必要的参数 --> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </default-config> </c3p0-config>
创建一个数据库:
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50729 Source Host : localhost:3306 Source Schema : books Target Server Type : MySQL Target Server Version : 50729 File Encoding : 65001 Date: 14/05/2021 18:06:26 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for books -- ---------------------------- DROP TABLE IF EXISTS `books`; CREATE TABLE `books` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号', `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '书名', `price` decimal(10, 2) NULL DEFAULT NULL COMMENT '价格', `publishDate` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '出版日期', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `title`(`title`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of books -- ---------------------------- INSERT INTO `books` VALUES (1, 'Java编程思想', 98.50, '2005-01-02 00:00:00'); INSERT INTO `books` VALUES (2, 'HeadFirst设计模式', 55.70, '2010-11-09 00:00:00'); INSERT INTO `books` VALUES (3, '第一行Android代码', 69.90, '2015-06-23 00:00:00'); INSERT INTO `books` VALUES (4, 'C++编程思想', 88.50, '2004-01-09 00:00:00'); INSERT INTO `books` VALUES (5, 'HeadFirst Java', 55.70, '2013-12-17 00:00:00'); INSERT INTO `books` VALUES (6, '疯狂Android', 19.50, '2014-07-31 00:00:00'); SET FOREIGN_KEY_CHECKS = 1;
然后编写我们对应数据库的实体类(Books.java)
public class Books { private Long Id; private String title; private String price; private String publishDate; public Books() { } public Books(Long id, String title, String price, String publishDate) { Id = id; this.title = title; this.price = price; this.publishDate = publishDate; } public Long getId() { return Id; } public void setId(Long id) { Id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } public String getPublishDate() { return publishDate; } public void setPublishDate(String publishDate) { this.publishDate = publishDate; } @Override public String toString() { return "Books{" + "Id=" + Id + ", title='" + title + '\'' + ", price='" + price + '\'' + ", publishDate='" + publishDate + '\'' + '}'; } }
编写我们的工具类(这里就是我们ORM框架的主要代码实现,主要采用JDBC和反射技术进行实现):
import com.mchange.v2.c3p0.ComboPooledDataSource; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class MyJDBCUtils { //创建数据库连接池 private static ComboPooledDataSource dataSource = new ComboPooledDataSource(); /*实现查找数据库的功能*/ public static <T> List<T> query(Class clazz, String sql, Object... args){ //获得连接对象 try(Connection conn = dataSource.getConnection()){ //获得命令对象 PreparedStatement preparedStatement = conn.prepareStatement(sql); //设置占位符参数 for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i+1,args[i]); } //执行查询,获得一个结果集 ResultSet resultSet = preparedStatement.executeQuery(); List<T> list = new ArrayList<>(); //逐行访问结果集 while (resultSet.next()){ //创建java对象来包装一行数据,这个对象就包含多个列了 Object obj = clazz.newInstance();//反射机制 //获得该类的所有属性 Field[] fields = clazz.getDeclaredFields(); //遍历属性 for (Field field : fields){ String name = field.getName(); //获得该列的值 Object value = resultSet.getObject(name); //因为属性是private的,所以不能访问,这里我们通过反射技术打开他访问的权限 field.setAccessible(true); //给该属性赋值 对象.属性 = 值 field.set(obj,castValue(field.getType(),value)); } list.add((T) obj); } return list; }catch (SQLException e){ e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } return null; } //实现更新数据库的功能 public static int update(String sql,Object... args) { //获得连接对象 try(Connection conn = dataSource.getConnection()){ //获得命令对象 PreparedStatement preparedStatement = conn.prepareStatement(sql); //设置占位符参数 for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i+1,args[i]); } //执行 int rows = preparedStatement.executeUpdate(); return rows; }catch (SQLException e){ e.printStackTrace(); } return -1; } //属性值的类型转换 public static Object castValue(Class valueType,Object value){ //就八大基本类型就好,还有其他很多类型,以后再加 if (valueType == Integer.class){ return Integer.valueOf(value.toString()); } if (valueType == Byte.class){ return Byte.valueOf(value.toString()); } if (valueType == Short.class){ return Short.valueOf(value.toString()); } if (valueType == Long.class){ return Long.valueOf(value.toString()); } if (valueType == Float.class){ return Float.valueOf(value.toString()); } if (valueType == Double.class){ return Double.valueOf(value.toString()); } if (valueType == Boolean.class){ return Boolean.valueOf(value.toString()); } if (valueType == Character.class){ //字符类型直接取得他的字符就行 return value.toString().charAt(0); } return value.toString(); } }
接下来我们对工具类进行测试(MyTest.java):
import java.util.List; public class MyTest { public static void main(String[] args) { List<Books> books = MyJDBCUtils.query(Books.class, "select * from books"); System.out.println(books); } }
输出结果:
[Books{Id=1, title='Java编程思想', price='98.50', publishDate='2005-01-02 08:00:00.0'}, Books{Id=2, title='HeadFirst设计模式', price='55.70', publishDate='2010-11-09 08:00:00.0'}, Books{Id=3, title='第一行Android代码', price='69.90', publishDate='2015-06-23 08:00:00.0'}, Books{Id=4, title='C++编程思想', price='88.50', publishDate='2004-01-09 08:00:00.0'}, Books{Id=5, title='HeadFirst Java', price='55.70', publishDate='2013-12-17 08:00:00.0'}, Books{Id=6, title='疯狂Android', price='19.50', publishDate='2014-07-31 08:00:00.0'}]
目录结构: