@maloyau

Генерация JSON с вложенными объектами?

Есть две сущности:

City:
@Entity
@Table(name = "cities")
public class City {
    @Id
    @GeneratedValue
    private long city_id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;

     //Конструкторы, геттеры, сеттеры
}
и

Country:
@Entity
@Table(name = "countries")
public class Country {
    @Id
    @GeneratedValue
    private long country_id;
    @Column(nullable = false, unique = true)
    private String name;
    @OneToMany(mappedBy = "country")
    private List<City> cityList;

     //Конструкторы, геттеры, сеттеры
}
Слой доступа к данным:
public class CityDaoImpl implements CityDao {
     //...
    @Override
    public List<City> getCityById(long id){
        Session session = HibernateUtil.getSessionFactory().openSession();
        List<City> cityList = null;
        try {
            Criteria criteria = session.createCriteria(City.class);
            criteria.add(Restrictions.eq("city_id", id));
            cityList = (List<City>)criteria.list();
        } catch (Exception e) {
            e.printStackTrace();
        }   finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
        return cityList;
    }
}
, метод которого getCityById(long id), успешно возвращает Объект класса City c вложенным объектом класса Country. Проблемы появились после того, как попытался Объект City возвращаемый данным методом запихнуть в JSON:
public static void main(String[] args) {
        CityDao cityDao = new CityDaoImpl();
        // Прошу не придираться к отсутсвию вылова ексепшнов
        City city = cityDao.getCityById(1).get(0); 
        ObjectMapper mapper = new ObjectMapper();
        // Выводим в json файл
        mapper.writeValue(new File("F:\\city.json"), city);
        // Выводим на консоль
        System.out.println(mapper.writeValueAsString(city));     
    }
, с появлением вот таких ругательств: com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.serhii.entity.Country.cityList, could not initialize proxy - no Session (through reference chain: com.serhii.entity.City["country"]->com.serhii.entity.Country["cityList"])...

P.S. Прошу отнестись с снисхождением к "огрехам", так как только учусь :-) Но замечания и тычки пальцем на ошибки буду рад услышать!
... Изначально думал, что нужно играться с FetchType в аннотации @ManyToOne, но оказалось не оно...
  • Вопрос задан
  • 1217 просмотров
Решения вопроса 2
LeEnot
@LeEnot
Енот-андроид
Вам говорят, что вы пытаетесь обратиться к lazy-loaded collection вне сессии Hibernate. Можно поменять тип загрузки, можно добавить @JsonIgnore перед @OneToMany
Ответ написан
Комментировать
@Braidner
Аннотация OneToMany дефолтно имеет fetch Lazy, т.е. Hibernate попытается проинициализировать ее при обращении к коллекции. Если у него не будет открытой сессии, то он выплюнет исключение.
Но поставив fetch Eager должна вылететь новое исключение stack over flow, из-за рекурсивных зависимостей country<=>city. Для этого в Jacson есть аннотации @JsonManagedReference и @JsonBackReference.
Посмотрите 2 полезные ссылки:
stackoverflow.com/questions/3325387/infinite-recur...
https://github.com/FasterXML/jackson-datatype-hibernate
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы