java反射在数据库上的应用
一、java反射:1.在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。 2.对于任意一个对象,都能够调用它的任意一个方法。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
二、反射在数据库上的应用:传统的数据库操作代码为,每个表格创建dao类效率低。一个dao方法,四个方法操作,传入不同对象。反射机制用来做重复有规则事情。保存数据时,把需要保存的对象的属性值全部取出来再拼凑sql语句即可。
三、实际应用:hibernate、struts都是用反射机制实现的,更新软件新功能时不需要重新编译用户安装,运行时动态创建和编译可实现,是一种解释操作慢于直接执行操作。
四、举个例子:
创建数据库Websites表格,编写一个对应javabean的Websites类,编写一数据库连接类,编写一个反射机制实现的数据库操作dao类,编写一个测试类即可。
1.建websites表:
/*
Navicat MySQL Data Transfer
Source Server : 127.0.0.1
Source Server Version : 50621
Source Host : localhost
Source Database : RUNOOB
Target Server Version : 50621
File Encoding : utf-8
Date: 05/18/2016 11:44:07 AM
*/
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `websites`
-- ----------------------------
DROP TABLE IF EXISTS `websites`;
CREATE TABLE `websites` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL DEFAULT '' COMMENT '站点名称',
`url` varchar(255) NOT NULL DEFAULT '',
`alexa` int(11) NOT NULL DEFAULT '0' COMMENT 'Alexa 排名',
`country` char(10) NOT NULL DEFAULT '' COMMENT '国家',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `websites`
-- ----------------------------
BEGIN;
INSERT INTO `websites` VALUES ('1', 'Google', 'https://www.google.cm/', '1', 'USA'), ('2', '淘宝', 'https://www.taobao.com/', '13', 'CN'), ('3', '菜鸟教程', 'http://www.runoob.com/', '4689', 'CN'), ('4', '微博', 'http://weibo.com/', '20', 'CN'), ('5', 'Facebook', 'https://www.facebook.com/', '3', 'USA');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
2.编写表对应的javabean(Websites.java):
package model;
public class Websites {
private int id;
private String name;
private String url;
private int alexa;
private String country;
@Override
public String toString() {
// TODO Auto-generated method stub
return "website{" + "id=" + id + ", name='" + name + '\'' + ", url='" + url + '\'' + ", alexa='" + alexa + '\''
+ ", country='" + country + '\'' + "}";
}
public Websites() {
super();
}
public Websites(int id, String name, String url, int alexa, String country) {
super();
this.id = id;
this.name = name;
this.url = url;
this.alexa = alexa;
this.country = country;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getAlexa() {
return alexa;
}
public void setAlexa(int alexa) {
this.alexa = alexa;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
3.编写数据库连接(GetConnection.java):
package control;
import java.sql.Connection;
import java.sql.DriverManager;
public class GetConnection {
public Connection getCon() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/runoob", "root", "86165772cbg");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return conn;
}
}
4.运用反射机制实现数据库dao(DaoImpl.java):
package control;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class DaoImpl {
public <T> List<T> select(T t) throws SQLException, InstantiationException, IllegalAccessException {
// 获取对象名
String sql = "select * from " + t.getClass().getSimpleName();
List<T> li = new ArrayList<T>();
Connection con = new GetConnection().getCon();
ResultSet res = con.prepareStatement(sql).executeQuery();
// 其中prepareStatement可通过setString对占位符放值
// 转化为ResultSetMetaData对象
ResultSetMetaData md = res.getMetaData();
int count = md.getColumnCount();
// 获取java对象的属性数组
Field[] fields = t.getClass().getDeclaredFields();
while (res.next()) {
// 泛型实例化
T t2 = (T) t.getClass().newInstance();
for (int i = 0; i < fields.length; i++) {
// 输出当前属性
System.out.println(fields[i]);
// 遍历结果集中的对象的属性
for (int k = 0; k < count; k++) {
String columnName = md.getColumnName(k + 1);
if (fields[i].getName().toUpperCase().equals(columnName.toUpperCase())) {
// 修改类的accessible为true,使得当前属性可以修改
fields[i].setAccessible(true);
// res.getObject(columnName)获取这条信息的列名的数据
// 调用field的set方法,给当前对象赋值
fields[i].set(t2, res.getObject(columnName));
}
}
}
li.add(t2);
}
return li;
}
public <T> T update(T t) {
try {
Field[] fields = t.getClass().getDeclaredFields();
fields[0].setAccessible(true);
String tiao = "";
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
if (field.getType().equals(String.class)) {
tiao += field.getName() + "='" + field.get(t) + "',";
} else {
tiao += field.getName() + "='" + field.get(t) + "',";
}
}
// $解释为行的结尾
tiao = tiao.split(",$")[0];
String sql = "update " + t.getClass().getSimpleName() + " set " + tiao + " where " + fields[0].getName()
+ " =" + fields[0].get(t);
System.out.println(sql);
int records = new GetConnection().getCon().prepareStatement(sql).executeUpdate();
System.out.println(records);
if (records > 0) {
System.out.println("Successful!");
} else {
System.out.println("Error!");
}
} catch (SQLException | IllegalAccessException e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
public <T> T insert(T t) throws IllegalArgumentException, IllegalAccessException {
Field[] fields = t.getClass().getDeclaredFields();
String columnName = "";
String columnValue = "";
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
if (fields[i].get(t) == null) {
continue;
}
columnName += fields[i].getName() + ",";
if (fields[i].getType().equals(String.class)) {
columnValue += "'" + fields[i].get(t) + "'" + ",";
} else {
columnValue += fields[i].get(t) + ",";
}
}
columnName = columnName.split(",$")[0];
columnValue = columnValue.split(",$")[0];
String sql = "insert into " + t.getClass().getSimpleName() + "(" + columnName + ")values("
+ columnValue + ")";
System.out.println(sql);
try {
int records = new GetConnection().getCon().prepareStatement(sql).executeUpdate();
if (records > 0) {
System.out.println("Successful!");
} else {
System.out.println("Error!");
}
} catch (SQLException e) {
// TODO: handle exception
}
return null;
}
public <T> T delete(T t) throws SQLException {
Field field = t.getClass().getDeclaredFields()[0];
field.setAccessible(true);
try {
String sql = "delete from " + t.getClass().getSimpleName() + " where " + field.getName() + " = "
+ field.get(t);
System.out.println(sql);
int records = new GetConnection().getCon().prepareStatement(sql).executeUpdate();
if (records > 0) {
System.out.println("Successful!");
} else {
System.out.println("Error!");
}
} catch (IllegalAccessException e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
}
5.测试用例(WebsitesTest.java):
package view;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import control.DaoImpl;
import model.Websites;
public class WebsitesTest {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, SQLException {
DaoImpl dao = new DaoImpl();
Websites websites = new Websites();
List<Websites> li = new ArrayList<Websites>();
// 查询测试
// li = dao.select(websites);
// for (int i = 0; i < li.size(); i++) {
// System.out.println(li.get(i).toString());
// }
插入测试
// Websites websites1 = new Websites(6, "百度", "https://www.baidu.com/", 10, "CN");
// dao.insert(websites1);
// 更新测试
// Websites websites2 = new Websites(6, "百度", "https://www.baidu.com/", 5, "CN");
// dao.update(websites2);
// 删除测试
Websites websites3 = new Websites(6, "百度", "https://www.baidu.com/", 5, "CN");
dao.delete(websites3);
}
}