使用JDBC封装ORM框架操作MySql数据库
使用JDBC封装ORM框架操作MySql数据库
一 添加mvn依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-Java</artifactId>
<version>6.0.5</version>
</dependency>
二 创建db.properties数据库配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/my_dev?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
jdbc.username=root
jdbc.password=admin
可以看到我这里加载的驱动是com.mysql.cj.jdbc.Driver而不是com.mysql.jdbc.Driver,这是因为我这里使用的是mysql6.0以上的版本,如果使用之前驱动会报一个警告:Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
打开com.mysql.jdbc.Driver.class查看源码可以发现,其继承了com.mysql.cj.jdbc.Driver,并且类加载的时候就输出一个警告。再看com.mysql.cj.jdbc.Driver.class类,可以看到其在类加载的时候把自己注册到了DriverManager中。
我们再来看一下5.1.10版本中的com.mysql.jdbc.Driver.class源码,可以看到以前是在这个类中把自己给注册到了DriverManager中。
另外jdbc.url中我们也发现了陌生的两个参数:serverTimezone=UTC useSSL=false 如果不添加会报两个错误:Sun Apr 22 22:59:22 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Exception in thread "main" java.sql.SQLException: The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
一个说的是在5.5.45+/5.6.26+ /5.7.6+版本中要显示的指定是否使用SSL连接,而useSSL=false就是指定不使用。
第二行是说要指定时区,ServerTimezone=UTC就是指定当前时区为世界标准时间
三 创建通用Connection工具类
public class DBHelper {
private static final Properties properties;
private static String driver; //数据库驱动
private static String url; //数据库地址
private static String username; //用户名
private static String password; //密码
private static final String JDBC_PROPERTIES_PATH="config/db.properties"; //配置文件路径
static{
properties=new Properties();
try {
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(JDBC_PROPERTIES_PATH));
driver=properties.getProperty("jdbc.driver");
url=properties.getProperty("jdbc.url");
username=properties.getProperty("jdbc.username");
password=properties.getProperty("jdbc.password");
}catch(Exception e){
e.printStackTrace();
}
}
public static Connection getConnection() throws Exception{
Class.forName(driver);
Connection connection=DriverManager.getConnection(url,username,password);
return connection;
}
public static void closeResource(Connection conn)throws Exception{
closeResource(conn,null);
}
public static void closeResource(Connection conn,PreparedStatement pst)throws Exception{
closeResource(conn,pst,null);
}
public static void closeResource(Connection conn, PreparedStatement pst, ResultSet rs)throws Exception{
if(rs!=null){
rs.close();
}
if(pst!=null){
pst.close();
}
if(conn!=null){
conn.close();
}
}
}
四 创建通用basedao类
public class JDBCBaseDao<T,ID extends Serializable>{
private Class classzz;
public JDBCBaseDao(){
Type type=this.getClass().getGenericSuperclass(); //获取直接继承父类及其类型参数
ParameterizedType ptype=(ParameterizedType)type;
Type[] types=ptype.getActualTypeArguments(); //获取所有泛型内的参数类型
this.classzz=(Class)types[0]; //取第一个类型
}
public List<T> query(String sql)throws Exception{
return query(sql,null);
}
public List<T> query(String sql,Object[] params)throws Exception{
Connection conn=DBHelper.getConnection();
PreparedStatement pst=conn.prepareStatement(sql);
if(params!=null) {
for (int i=0;i<params.length;i++){
pst.setObject(i+1,params[i]);
}
}
ResultSet rs=pst.executeQuery();
List<T> datas=convertEntity(rs);
DBHelper.closeResource(conn,pst,rs);
return datas;
}
/**
* 获取类名
* @return
*/
public String getTableName(){
return classzz.getSimpleName();
}
/**
* 构造一个oid的sql
* @param tableName
* @return
*/
public String buildOidSql(String tableName){
return "select * from "+tableName+ " where id=?";
}
/**
* 根据id查询
* @param id
* @return
* @throws Exception
*/
public T queryById(ID id) throws Exception{
String oIdSql=buildOidSql(getTableName()); //构造oid查询sql
T entity=query(oIdSql,new Object[]{id}).get(0);
return entity;
}
/**
* 结果集转换为实体类
* @param rs
* @return
* @throws Exception
*/
private List<T> convertEntity(ResultSet rs)throws Exception{
List<T> datas=new ArrayList<T>();
Field[] fields=classzz.getDeclaredFields(); //反射获取类的所有属性
ResultSetMetaData metaData=rs.getMetaData(); //获取数据表的元数据
int columnCount=metaData.getColumnCount(); //获取返回数据的列总数
while(rs.next()){
Object obj=classzz.getDeclaredConstructor().newInstance(); //实例化实体对象
for(int i=0;i<columnCount;i++){
String columnLabel= metaData.getColumnLabel(i+1); //获取as后的字段名
Object value=rs.getObject(columnLabel); //获取该字段的值
for(int fieldIndex=0;fieldIndex<fields.length;fieldIndex++){
Field field=fields[fieldIndex];
if(columnLabel.equals(field.getName())){ //字段名和属性名相同
field.setAccessible(true); //允许暴力访问private修饰的属性
field.set(obj,value); //给属性赋值
break;
}
}
}
datas.add((T)obj);
}
return datas;
}
}
五 创建UserInfo实体类
public class UserInfo {
private Integer id;
private String name;
private String login_name;
private String password;
private String email;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLogin_name() {
return login_name;
}
public void setLogin_name(String login_name) {
this.login_name = login_name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return id+":"+name+":"+login_name+":"+password+":"+email;
}
}
六 创建UserInfoDao.java
public class UserInfoDao extends JDBCBase <UserInfo,Integer> {
}
七 测试调用
本次完成了使用JDBC搭建了一个ORM框架,简单实现了oid查询,以及sql查询和sql参数查询,这里阐述了思路,大家可以完善其他的方法,例如更新以及新增。
本示例项目代码在git中可以下载:https://github.com/chenliancheng/JDBC-ORM
推荐阅读