这个demo只是很简单对实体和数据层之间的交互做了封装,没有考虑复杂的情况有很多方法只是支持最原始的单表,不支持级联查询。
思路:
数据库-》实体:数据库查询结果转化为MAP,使用反射获取实体对应的数据库字段名,通过MAP拼接数据,使用JSON转化为实体。
实体-》数据库:反射获取实体数据库字段和表名,拼接SQL。
简单执行效果:
实体:
package com.mvc.eitity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Table(name = "userInfo")
public class User {
@Id
@Column(name = "id")
private final int id;
@Column(name = "name")
// @Size(min = 2,max = 6,message = "名称不符合要求")
private String name;
@Column(name = "age")
// @Size(min = 1,max = 3,message = "年龄不符合要求")
@NotNull(message = "年龄不能空")
private String age;
@Column(name = "pwd")
private String passWord;
public User(int id,String name,String age,String pwd){
this.id = id;
this.name = name;
this.age = age;
this.passWord = pwd;
}
public User(){
this(0,null,null,null);
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
@Override
public String toString() {
return "********id : " + getId() + "***Name :" + getName() + "******* age : " + age;
}
}
业务层:
package com.mvc.service.impl;
import com.mvc.dao.UserDao;
import com.mvc.eitity.User;
import com.mvc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public User queryUserById(String userId) {
StringBuilder sql = new StringBuilder("select * from userinfo where id =" + userId);
try{
return userDao.execQuerySQLForEntity(User.class, sql.toString());
}catch (Exception e){
e.printStackTrace();
}
return null;
}
@Override
public List<User> queryUserList(User user) {
StringBuilder sql = new StringBuilder("select * from userinfo ");
try{
return userDao.execQuerySQLForEntityList(User.class, sql.toString());
}catch (Exception e){
e.printStackTrace();
}
return null;
}
@Override
public void saveUser(User user) {
try {
userDao.saveUser(user);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
数据层:
package com.mvc.dao;
import com.mvc.eitity.User;
import com.mvc.utils.DaoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.web.context.ContextLoader;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
@Repository
public class UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
private JdbcTemplate getJdbcTemplate(){
return jdbcTemplate;
}
/**
* 查询实体集合
* @param tClass 实体类
* @param sql 执行SQL
* @param params SQL参数
* @param <T>
* @return
*/
public <T> List<T> execQuerySQLForEntityList(Class<T> tClass,String sql,String ... params) throws InstantiationException, IllegalAccessException {
List<Map<String, Object>> maps = getJdbcTemplate().queryForList(sql, params);
return DaoUtil.convertSQLResultForEntityList(tClass, maps);
}
/**
* 查询实体
* @param tClass
* @param sql
* @param params
* @param <T>
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
public <T> T execQuerySQLForEntity(Class<T> tClass,String sql,String ... params)throws InstantiationException, IllegalAccessException {
Map <String, Object> maps = getJdbcTemplate().queryForMap(sql, params);
return DaoUtil.convertSQLResultForEntity(tClass, maps);
}
/**
* 保存方法
* @param user
* @throws IllegalAccessException
*/
public void saveUser(User user) throws IllegalAccessException {
String sql = DaoUtil.convertEntityForSQL(user);
jdbcTemplate.execute(sql);
}
/**
* 保存方法
* @param user
* @throws IllegalAccessException
*/
public void save(User user) throws IllegalAccessException {
String sql = DaoUtil.convertEntityForSQL(user);
jdbcTemplate.execute(sql);
}
}
DaoUtils:实体转化为SQL,查询结果转化为实体工具类
package com.mvc.utils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mvc.eitity.User;
import com.mvc.eitity.base.TableStructure;
import org.junit.Test;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.util.*;
public class DaoUtil {
/**
* 表结构Map
*/
public static final Map<String,TableStructure> tableMap = new HashMap<>();
/**
* 封装spring template数据,返回对应实体
*
* @param <T>
* @param tClass
* @param result
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static <T> List<T> convertSQLResultForEntityList(Class<T> tClass, List<Map<String, Object>> result) throws IllegalAccessException, InstantiationException {
if(tClass == null || result == null){
throw new NullPointerException("Class or resultData is null");
}
//获取实体
final Map<String, String> columnFiledMap = columnFiledMap(tClass);
List<T> resultList = new ArrayList<>();
Gson gson = JsonUtil.getGson();
for(Map<String,Object> data : result){
resultList.add(convertSQLResultForEntity(tClass, data, columnFiledMap));
}
return resultList;
}
/**
* 读取实体中注解内容,封装为字段名称和值
* @param tClass
* @return
*/
public static Map<String,String> columnFiledMap(Class tClass){
Map<String,String> columnFiledMap = new LinkedHashMap<>(16);
Field[] fields = tClass.getDeclaredFields();
for(Field field : fields){
field.setAccessible(true);
Column annotation = field.getAnnotation(Column.class);
if(annotation != null){
columnFiledMap.put(annotation.name(),field.getName());
}
}
return columnFiledMap;
}
/**
* 拼接字段和值转化实体
* 实体的转换没有用到SET方法去注入
* 而是选择了使用MAP通过JSON直接转化为实体
* @param tClass
* @param data
* @param columnFiledMap
* @param <T>
* @return
*/
public static <T> T convertSQLResultForEntity(Class<T> tClass,Map<String,Object> data,Map<String,String> columnFiledMap){
Map<Object,Object> newObjectValue = new HashMap<>();
for(Map.Entry<String,Object> entry : data.entrySet()){
String newFiled = columnFiledMap.get(entry.getKey());
newObjectValue.put(newFiled,entry.getValue());
}
return JsonUtil.formJson(JsonUtil.formatJson(newObjectValue), tClass);
}
/**
* 转化实体为SQL,保存方法
* @param ob
* @return
* @throws IllegalAccessException
* 这个方法有缺陷,生成的SQL字段顺序不是和数据库中对应的,后续准备优化
*/
public static synchronized String convertEntityForSQL(Object ob) throws IllegalAccessException {
StringBuffer sql = new StringBuffer("insert into ");
Class<?> aClass = ob.getClass();//获取传入对象的Class
Field[] fields = aClass.getDeclaredFields();//反射获取对象的私有化字段
Table entity = aClass.getAnnotation(Table.class);//获取实体中表名
sql.append(entity.name());
TreeSet<String> rowSet = new TreeSet<>();
LinkedList<Object> valSet = new LinkedList<>();
for(Field field : fields){//这里不想写两次循环所以没有调用上面的方法
field.setAccessible(true);
Column annotation = field.getAnnotation(Column.class);//获取Column注解的字段名称
Id id = field.getAnnotation(Id.class);
if(annotation != null){
if(id!= null){
continue;//判断是否有ID注解,因为数据库里面id设置为自增所以拼接SQL的时候不用拼接ID
}
rowSet.add(annotation.name());
valSet.add(String.valueOf(field.get(ob)));
}
}
sql.append(disposeRowSQL(rowSet.toString()));
sql.append(" VALUES (");
for(Object val :valSet){
sql.append("'" + val + "',");
}
if(sql.toString().endsWith(",")){
sql.replace(sql.length() -1,sql.length(),"");
}
sql.append(")");
return sql.toString();
}
public static <T> T convertSQLResultForEntity(Class<T> tClass,Map<String,Object> data){
Map<String, String> stringStringMap = columnFiledMap(tClass);
return convertSQLResultForEntity(tClass,data,stringStringMap);
}
private static String disposeRowSQL(String arg){
return arg.replaceAll("\\[","(").replaceAll("\\]",")");
}
@Test
public void junitOne() throws IllegalAccessException {
convertEntityForSQL(new User(2,"2","3","4"));
}
@Test
public void daoTest() throws IllegalAccessException {
String s = convertEntityForSQL(new User(0, "a", "a", "b"));
System.out.println(s);
}
}
第一次写反射方法不对请留言,谢谢。