创建一个项目,导入所需要的依赖包
这两个包分别是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'}]
目录结构: