您的位置:首页 > 数据库

hibernate通过反射,动态生成insert语句原理 并向数据库添加数据

2017-03-09 23:52 561 查看
hibernate中的反射机制,实现逆向访问数据库,并封装insert方法

首先,我们写dao层的时候会发现,有很多insert语句,比如: insert into Users(username,password) values('zhangsan','zs123') 。开发过程中会遇到很多这样的插入语句,为了简化开发,Hibernate框架实现语句的封装,

为了更好的理解,我们下面通过反射机制来模拟封装insert方法  和通过Hibernate实现逆向访问数据库,并调用上面封装好的insert方法向数据库中动态插入数据。

1.Hibernate实现逆向访问数据库

1)首先我们需要的实体类 Users

public class Users {
private Integer id; // 编号
private String username; // 账户
private String password;// 密码
private Integer state_id; // 职位状态
public void setId(Integer id) 		 {this.id = id;}
public Integer getId()			 {return id;}
public void setUsername(String username) {this.username = username;}
public String getUsername()		 {return username;}
public void setPassword(String password) {this.password = password;}
public String getPassword() 		 {return password;}
public void setState_id(Integer state_id){this.state_id = state_id;}
public Integer getState_id()             {return state_id;}
public Users() {}
public Users(Integer id, String username, String password, Integer state_id) {
this.id = id;
this.username = username;
this.password = password;
this.state_id = state_id;
}

@Override
public String toString() {
return "Users [id=" + id + ", username=" + username + ", password=" + password + ", state_id=" + state_id + "]";
}
}


2) 配置连接数据库的属性文件 test.properites

mysql.username=root
mysql.password=mysqlpass
mysql.url=jdbc:mysql://localhost:3306/mydb?characterEncoding=utf-8
mysql.driverClassName=com.mysql.jdbc.Driver
3)编写连接数据库的工具类

public class ConnectMysqlUtil {
private static Connection con;
static {
// 使用反射加载属性文件:
InputStream in = Object.class.getResourceAsStream("/test.properties");
Properties pro = new Properties();
try {
pro.load(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 从输入流中读取属性列表(键和元素对)。
// 获取properties中的属性
String mysql_username = pro.getProperty("mysql.username").trim();
String mysql_password = pro.getProperty("mysql.password").trim();
String mysql_url = pro.getProperty("mysql.url").trim();
String mysql_driverClassName = pro.getProperty("mysql.driverClassName").trim();
try {
Class.forName(mysql_driverClassName);
con = DriverManager.getConnection(mysql_url, mysql_username, mysql_password);
} catch (ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getCon(){
return con;
}
}


通过上面的步骤,我们的准备工作已经做好了, 现在只需要编写工具类ReflexUtil来封装动态生成的insert语句 就可以了
重点:

public class ReflexUtil {

//获取并且返回完整的insert  语句
//String拼接
public static String getInsertSQL(Object o) {
Class c = o.getClass();
Field[] fl = c.getDeclaredFields();
String fieldName = "";//属性名拼接
String valueName = ""; //字段值拼接
for (Field field : fl) {
String str = field.getName(); //获取属性名
Method[] ms = c.getDeclaredMethods(); //获取方法
for (Method method : ms) {
String name = method.getName();//获取方法名
if(name.startsWith("get")&&!name.startsWith("getClass")){//过滤 筛选get方法
String str1 = name.substring(3);  //通过方法名截取出字段名
if(str.equalsIgnoreCase(str1)&&!"id".equalsIgnoreCase(str)){ //判断前面的属性名 是否 与截取出来的字段名相同 ,则说明顺序相同 ,则拼接
//去掉ID
fieldName += str + ",";
String str2;
try {
str2 = method.invoke(o, null).toString(); //获取方法值
String type = method.getReturnType().getSimpleName(); //方法类型
if("String".equalsIgnoreCase(type)){
valueName += "'"+str2+"'"+","; //数据库中 String类型  需要加单引号 插入
}else{
valueName +=str2+",";
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}
}
}
fieldName = fieldName.substring(0, fieldName.length()-1); //去除末尾的逗号
valueName = valueName.substring(0, valueName.length()-1);
String sql= "insert into "+c.getSimpleName()+"("+fieldName+")"+" values"+"("+valueName+")";
return sql;
}

//获取并且返回完整的insert  语句
//StringBuffer拼接
public static String getInsertSql(Object o){
Class c = o.getClass();
Field[] fl = c.getDeclaredFields();
StringBuffer fieldName= new StringBuffer();//属性名拼接
StringBuffer valueName=new StringBuffer() ; //字段值拼接
for (Field field : fl) {
String str = field.getName(); //获取属性名
Method[] ms = c.getDeclaredMethods(); //获取方法
for (Method method : ms) {
String name = method.getName();//获取方法名
if(name.startsWith("get")&&!name.startsWith("getClass")){//过滤 筛选get方法
String str1 = name.substring(3);  //通过方法名截取出字段名
if(str.equalsIgnoreCase(str1)&&!"id".equalsIgnoreCase(str)){ //判断前面的属性名 是否 与截取出来的字段名相同 ,则说明顺序相同 ,则拼接
//去掉ID
fieldName.append(str + ",") ;
String str2;
try {
str2 = method.invoke(o, null).toString();
String type = method.getReturnType().getSimpleName();
if("String".equalsIgnoreCase(type)){
valueName.append("'"+str2+"'"+",");
}else{
valueName.append(str2+",");
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
String endFieldName = fieldName.substring(0, fieldName.length()-1); //去除末尾的逗号
String endValueName = valueName.substring(0, valueName.length()-1);
String sql= "insert into "+c.getSimpleName()+"("+endFieldName+")"+" values"+"("+endValueName+")";
return sql;
}

}






最后编写测试类

public static void main(String[] args) throws SQLException {
Users users = new Users(1,"张三","zs1231",8);
String sql = ReflexUtil.getInsertSQL(users);
Connection con = ConnectMysqlUtil.getCon();
PreparedStatement psta = con.prepareStatement(sql);
int i = psta.executeUpdate();
if(i>0){
System.out.println("插入成功");
}
}
测试结果:





通过上面步骤:实现了Hibernate底层的东西,也让我们理解了Hibernate的实现原理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐