Home > Back-end >  How to map resultset into composite object in mapper class
How to map resultset into composite object in mapper class

Time:11-04

I have query which will return 8 columns for order placement POC, First 4 will be same for few rows(person details) and remaining 4 alone will differ(order details). Its a non normalized table.

COL1   COL2   COL3   COL4   COL5  COL6  COL7  COL8
-----------------------------------------------------
a      aaa    bbb    ccc    ddd   eee   fff   ggg
a      aaa    bbb    ccc    hhh   iii   jjj   kkk

My object looks like

class OrderBook{
   int id;
   int name;
   String age;
   String mailId;
   List<Order> orderList;
}

class Order{
   String productName;
   int price;
   int quantity;
   String address;
}

how can i loop through the result set and map the rows into the Orderbook object. Response should look something like below

{
   "id": 1,
   "name": "dude",
   "age" : 22,
   "mailId": "[email protected]",
   "orderList": [
        {
            "productName": "Milk",
            "price":23,
            "quantity":2,
            "address": "dude, 1st street"
        },
        {
            "productName": "Egg",
            "price":5,
            "quantity":10,
            "address": "dude, 1st street"
        }
    ]
}

I dont know how to loop it here

while(rs.next()){
    ???
}

CodePudding user response:

You should convert resultset to DataObject (OrderBook) firstly.

List<OrderBook> list = new ArrayList<>();
while(rs.next()){
   OrderBook orderBook = mapToOrderBook(rs);
   list.add(orderBook);
}

Few basic functions which you should write.

private List<OrderBook> getOrderBooks();
private OrderBook mapToOrderBook(ResultSet rs);

If you don't know how to get data from resultset:

https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html

Then you can use jackson to convert List to json data. Spring mvc already handled it for you.

@RequestMapping("/orderbooks")
public List<OrderBook> getOrderBooks() {
  return orderbookService.getOrderBooks();
}

CodePudding user response:

If you are using ResultSet directly you have to implement transformers directly from RS to Object instance. And use it from your DAO layer Something like:

@Override
public User getByID(int id) {
    OrderBook book = new OrderBook();
    try {
        PreparedStatement select = OrderBookTransformer.getInstance().getSelectStatementById(id);
        ResultSet rs = select.executeQuery();
        while (rs.next()) {
            book = OrderBookTransformer.getInstance().fromRsToObject(rs);
        }
    } catch (SQLException e) {
        log.error(e);
    }
    return book;
}

Where OrderBookTransformer could be like:

@Override
public OrderBook fromRsToObject(ResultSet rs) {
    OrderBook book = new OrderBook();
    try {
        user.setId(rs.getInt("id"));
        user.setName(rs.getInt("name"));
        user.setAge(rs.getString("age"));
        // set other fields
    } catch (SQLException e) {
        log.error(e);
    }
    return user;
}

For the initialisation transformer I used the Singleton pattern:

public class OrderBookTransformer implements BaseTranformer<OrderBook> {

    private static final Logger log = Logger.getLogger(OrderBookTransformer.class);
    private static OrderBookTransformer instance = null;

    protected OrderBookTransformer() {
    }

    public static OrderBookTransformer getInstance() {
        if (instance == null) {
            instance = new OrderBookTransformer();
        }
        return instance;
    }

And select statement something like:

@Override
public PreparedStatement getSelectStatementById(int id) {
    PreparedStatement select = null;
    try (Connection connection = ConnectionManager.getConnection()) {
        select = connection
                .prepareStatement("SELECT FROM order_books WHERE id = ?");
        select.setInt(1, id);
    } catch (SQLException e) {
        log.error(e);
    }
    return select;
}

My suggestion will be to use Spring Data instead of processing the Result Set directly.

You will need to do just a few more steps:

  • add spring data dependency to your build tool
  • add JPA annotations to your model with relations to it:
    @Entity
    class OrderBook {
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       private Integer id;
       private Integer name;
       private String age;
       private String mailId;
    
       @ElementCollection(targetClass = Order.class, fetch = FetchType.EAGER)
        @CollectionTable(name = "orders", joinColumns = @JoinColumn(name = "book_id"))
       private List<Order> orderList;
       // no args constructor   getters/setters
    }
    
    @Entity
    class Order {
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       private String productName;
       private Integer price; // consider use Double here
       private Integer quantity;
       private String address;
    }
  • create a repository for this class:

public OrderBookRepository implements JpaRepository<OrderBook, Integer> {}

and use it for retrieving data from DB.

  • Related