Java 将JDBC结果集映射到对象
我有一个用户类,它有16个属性,比如firstname、lastname、dob、username、password等等。。。这些都存储在MySQL数据库中,当我想要检索用户时,我使用ResultSet。我想将每个列映射回用户属性,但我这样做似乎效率非常低。 例如,我正在做:Java 将JDBC结果集映射到对象,java,mysql,object,jdbc,resultset,Java,Mysql,Object,Jdbc,Resultset,我有一个用户类,它有16个属性,比如firstname、lastname、dob、username、password等等。。。这些都存储在MySQL数据库中,当我想要检索用户时,我使用ResultSet。我想将每个列映射回用户属性,但我这样做似乎效率非常低。 例如,我正在做: //ResultSet rs; while(rs.next()) { String uid = rs.getString("UserId"); String fname = rs.getString("Firs
//ResultSet rs;
while(rs.next()) {
String uid = rs.getString("UserId");
String fname = rs.getString("FirstName");
...
...
...
User u = new User(uid,fname,...);
//ArrayList<User> users
users.add(u);
}
//结果集rs;
while(rs.next()){
stringuid=rs.getString(“UserId”);
String fname=rs.getString(“FirstName”);
...
...
...
用户u=新用户(uid、fname,…);
//ArrayList用户
用户。添加(u);
}
i、 e我检索所有列,然后通过将所有列值插入用户构造函数来创建用户对象
有人知道一种更快、更整洁的方法吗?无需将结果集值存储到字符串中,然后再次设置到POJO类中。而是在检索时设置 或者最好切换到像hibernate这样的ORM工具,而不是直接将POJO对象映射到数据库的JDBC 但到目前为止,请使用:
List<User> users=new ArrayList<User>();
while(rs.next()) {
User user = new User();
user.setUserId(rs.getString("UserId"));
user.setFName(rs.getString("FirstName"));
...
...
...
users.add(user);
}
List users=new ArrayList();
while(rs.next()){
用户=新用户();
user.setUserId(rs.getString(“UserId”);
user.setFName(rs.getString(“FirstName”);
...
...
...
用户。添加(用户);
}
如果要检索更多记录,请使用语句获取大小。像这样
Statement statement = connection.createStatement();
statement.setFetchSize(1000);
除此之外,我不认为你的表现有什么问题
就整洁而言。始终使用分离方法委托将结果集映射到POJO对象。以后可以在同一类中重用
像
如果columnName和object的fieldName的名称相同,还可以编写反射实用程序将记录加载回POJO。并使用元数据读取列名称。但对于小规模项目来说,使用反射并不是问题。但正如我之前所说的,你现在的做法没有任何问题 如果您不想使用任何JPA提供程序,如OpenJPA或Hibernate,您可以尝试使用ApacheDButils 那么您的代码将如下所示:
QueryRunner run = new QueryRunner(dataSource);
// Use the BeanListHandler implementation to convert all
// ResultSet rows into a List of Person JavaBeans.
ResultSetHandler<List<Person>> h = new BeanListHandler<Person>(Person.class);
// Execute the SQL statement and return the results in a List of
// Person objects generated by the BeanListHandler.
List<Person> persons = run.query("SELECT * FROM Person", h);
QueryRunner run=新的QueryRunner(数据源);
//使用BeanListHandler实现转换所有
//结果将行设置为Person JavaBeans的列表。
ResultSetHandler h=新BeanListHandler(Person.class);
//执行SQL语句并将结果返回到
//BeanListHandler生成的Person对象。
List persons=run.query(“从Person中选择*”,h);
假设您希望使用核心Java,而不使用任何战略框架。若您可以保证,实体的字段名将等于数据库中的列,那个么您可以使用反射API(否则在那个里创建注释并定义映射名)
按字段名
/**
Class<T> clazz - a list of object types you want to be fetched
ResultSet resultSet - pointer to your retrieved results
*/
List<Field> fields = Arrays.asList(clazz.getDeclaredFields());
for(Field field: fields) {
field.setAccessible(true);
}
List<T> list = new ArrayList<>();
while(resultSet.next()) {
T dto = clazz.getConstructor().newInstance();
for(Field field: fields) {
String name = field.getName();
try{
String value = resultSet.getString(name);
field.set(dto, field.getType().getConstructor(String.class).newInstance(value));
} catch (Exception e) {
e.printStackTrace();
}
}
list.add(dto);
}
DTO:
一样,但是
while(resultSet.next()) {
T dto = clazz.getConstructor().newInstance();
for(Field field: fields) {
Col col = field.getAnnotation(Col.class);
if(col!=null) {
String name = col.name();
try{
String value = resultSet.getString(name);
field.set(dto, field.getType().getConstructor(String.class).newInstance(value));
} catch (Exception e) {
e.printStackTrace();
}
}
}
list.add(dto);
}
思想
事实上,对所有字段进行迭代可能看起来无效,因此我将把映射存储在某个位置,而不是每次迭代。但是,如果我们的T
是一个仅用于传输数据的DTO,并且不包含大量不必要的字段,那就可以了。最后,它比一直使用样板方法要好得多
希望这对某人有所帮助。使用@TEH-EMPRAH创意和来自
导入注释.Column;
导入java.lang.reflect.Field;
导入java.lang.reflect.InvocationTargetException;
导入java.sql.SQLException;
导入java.util.*;
公共类对象映射器{
私人课堂;
私有映射字段=新HashMap();
映射错误=新建HashMap();
公共数据映射器(类clazz){
this.clazz=clazz;
List fieldList=Arrays.asList(clazz.getDeclaredFields());
用于(字段:字段列表){
Column col=field.getAnnotation(Column.class);
如果(列!=null){
字段。setAccessible(true);
fields.put(col.name(),field);
}
}
}
公共T映射(映射行)引发SQLException{
试一试{
T dto=(T)clazz.getConstructor().newInstance();
for(Map.Entry实体:row.entrySet()){
if(entity.getValue()==null){
continue;//不设置DBNULL
}
String column=entity.getKey();
Field=fields.get(列);
如果(字段!=null){
set(dto,convertInstanceOffObject(entity.getValue());
}
}
返回dto;
}catch(IllegalAccessException |实例化exception | NoSuchMethodException |调用targetexception e){
e、 printStackTrace();
抛出新的SQLException(“数据映射问题。请参阅日志”);
}
}
公共列表映射(列表行)引发SQLException{
列表=新建LinkedList();
用于(地图行:行){
列表。添加(地图(行));
}
退货清单;
}
私有T ConvertInstanceOffObject(对象o){
试一试{
返回(T)o;
}catch(ClassCastException e){
返回null;
}
}
}
关于它与数据库的关系,我有以下几点:
// connect to database (autocloses)
try (DataConnection conn = ds1.getConnection()) {
// fetch rows
List<Map<String, Object>> rows = conn.nativeSelect("SELECT * FROM products");
// map rows to class
ObjectMapper<Product> objectMapper = new ObjectMapper<>(Product.class);
List<Product> products = objectMapper.map(rows);
// display the rows
System.out.println(rows);
// display it as products
for (Product prod : products) {
System.out.println(prod);
}
} catch (Exception e) {
e.printStackTrace();
}
//连接到数据库(自动关闭)
try(DataConnection conn=ds1.getConnection()){
//取行
列表行=conn.nativeSelect(“从产品中选择*);
//将行映射到类
ObjectMapper ObjectMapper=新的ObjectMapper(Product.class);
列表产品=objectMapper.map(行);
//显示行
系统输出打印项次(行);
//将其显示为产品
用于(产品生产:产品){
系统输出打印项次(产品);
}
}捕获(例外e){
e、 printStackTrace();
}
使用DbUtils
我在这个库中遇到的唯一问题是,有时候bean类中有关系,而DBUtils没有映射这些关系。它
class SomeClass {
@Col(name = "column_in_db_name")
private String columnInDbName;
public SomeClass() {}
// ..
}
while(resultSet.next()) {
T dto = clazz.getConstructor().newInstance();
for(Field field: fields) {
Col col = field.getAnnotation(Col.class);
if(col!=null) {
String name = col.name();
try{
String value = resultSet.getString(name);
field.set(dto, field.getType().getConstructor(String.class).newInstance(value));
} catch (Exception e) {
e.printStackTrace();
}
}
}
list.add(dto);
}
import annotations.Column;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.*;
public class ObjectMapper<T> {
private Class clazz;
private Map<String, Field> fields = new HashMap<>();
Map<String, String> errors = new HashMap<>();
public DataMapper(Class clazz) {
this.clazz = clazz;
List<Field> fieldList = Arrays.asList(clazz.getDeclaredFields());
for (Field field : fieldList) {
Column col = field.getAnnotation(Column.class);
if (col != null) {
field.setAccessible(true);
fields.put(col.name(), field);
}
}
}
public T map(Map<String, Object> row) throws SQLException {
try {
T dto = (T) clazz.getConstructor().newInstance();
for (Map.Entry<String, Object> entity : row.entrySet()) {
if (entity.getValue() == null) {
continue; // Don't set DBNULL
}
String column = entity.getKey();
Field field = fields.get(column);
if (field != null) {
field.set(dto, convertInstanceOfObject(entity.getValue()));
}
}
return dto;
} catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
throw new SQLException("Problem with data Mapping. See logs.");
}
}
public List<T> map(List<Map<String, Object>> rows) throws SQLException {
List<T> list = new LinkedList<>();
for (Map<String, Object> row : rows) {
list.add(map(row));
}
return list;
}
private T convertInstanceOfObject(Object o) {
try {
return (T) o;
} catch (ClassCastException e) {
return null;
}
}
}
// connect to database (autocloses)
try (DataConnection conn = ds1.getConnection()) {
// fetch rows
List<Map<String, Object>> rows = conn.nativeSelect("SELECT * FROM products");
// map rows to class
ObjectMapper<Product> objectMapper = new ObjectMapper<>(Product.class);
List<Product> products = objectMapper.map(rows);
// display the rows
System.out.println(rows);
// display it as products
for (Product prod : products) {
System.out.println(prod);
}
} catch (Exception e) {
e.printStackTrace();
}
while(rs.next()) {
users.add(Q2Obj.fromResultSet(rs, User.class));
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.JSONObject;
import com.google.gson.Gson;
public class ObjectMapper {
//generic method to convert JDBC resultSet into respective DTo class
@SuppressWarnings("unchecked")
public static Object mapValue(List<Map<String, Object>> rows,Class<?> className) throws Exception
{
List<Object> response=new ArrayList<>();
Gson gson=new Gson();
for(Map<String, Object> row:rows){
org.json.simple.JSONObject jsonObject = new JSONObject();
jsonObject.putAll(row);
String json=jsonObject.toJSONString();
Object actualObject=gson.fromJson(json, className);
response.add(actualObject);
}
return response;
}
public static void main(String args[]) throws Exception{
List<Map<String, Object>> rows=new ArrayList<Map<String, Object>>();
//Hardcoded data for testing
Map<String, Object> row1=new HashMap<String, Object>();
row1.put("name", "Raja");
row1.put("age", 22);
row1.put("location", "India");
Map<String, Object> row2=new HashMap<String, Object>();
row2.put("name", "Rani");
row2.put("age", 20);
row2.put("location", "India");
rows.add(row1);
rows.add(row2);
@SuppressWarnings("unchecked")
List<Dto> res=(List<Dto>) mapValue(rows, Dto.class);
}
}
public class Dto {
private String name;
private Integer age;
private String location;
//getters and setters
}