ManyToOne在两个表中为每个新对象创建一个新条目

问题描述 投票:0回答:2

我有城市和天气。天气应指向数据库中的城市对象。一个城市可以有多个天气条目。我的问题是,每次向数据库添加天气时,都会创建一个具有相同名称但其他ID的新城市。

天气实体;

@Entity
public class Weather implements Serializable{

    @Id
    @GeneratedValue
    private int id;
    private static final long serialVersionUID = -3562151396218034738L;
    private LocalDateTime timeStamp;
    private Float windSpeed;
    private Float windDir;
    private Float humidity;
    private Float temperature;
    private String weatherDescription;
    @ManyToOne(fetch=FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinColumn(name="city_id")
    private City city;

    public Weather(){}

    public Weather(LocalDateTime timeStamp, Float windSpeed, Float windDir, Float humidity, Float temperature, String weatherDescription, City city){
        this.timeStamp = timeStamp;
        this.windSpeed = windSpeed;
        this.windDir = windDir;
        this.humidity = humidity;
        this.temperature = temperature;
        this.weatherDescription = weatherDescription;
        this.city = city;
    }
}

城市实体:

@Entity
public class City implements Serializable {

    @Id
    @GeneratedValue
    private int id;
    private static final long serialVersionUID = 1L;
    private String cityName;
    private String cityPostalcode;
    @OneToMany(mappedBy = "city")
    private List<Weather> weather;

    public City(){}

    public City(String cityName, String cityPostalcode){
    this.cityName = cityName;
    this.cityPostalcode = cityPostalcode;
    }

我的两种向数据库添加天气的方法。

    @Override
    public Weather addWeather(Weather weather) throws Exception {

        EntityManager em = JpaUtil.createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(weather);
            em.persist(weather.getCity());
            em.getTransaction().commit();
        } catch (Exception e) {
            if (em.getTransaction().isActive()) {
                em.getTransaction().rollback();
            }
            throw new RuntimeException(e);
        } finally {
            if (em.isOpen()) {
                em.close();
                LOG.info("New Weather entry for " + weather.getCity().getCityName());
            }
        }
        return weather;

    }

    @Override
    public List<Weather> addWeatherWithList(List<Weather> weather) throws Exception {

        for (int i = 0; i < weather.size() - 1; i++) {
                EntityManager em = JpaUtil.createEntityManager();
                em.getTransaction().begin();
                try {
                    em.persist(weather.get(i));
                    em.persist(weather.get(i).getCity());
                    em.getTransaction().commit();
                } catch (Exception e) {
                    if (em.getTransaction().isActive()) {
                        em.getTransaction().rollback();
                    }
                    throw new RuntimeException(e);
                } finally {
                    if (em.isOpen()) {
                        em.close();
                        LOG.info(weather.get(i).toString() + " added to db");
                    }
                }
        }
        return weather;

    }

我的餐桌天气:

enter image description here

我的餐桌城市:(目前我的天气数据仅来自这个城市,是的)

enter image description here

我现在真的在搜索任何东西,我有点无助。这里列出了我到目前为止尝试过的内容(至少我能记住的所有内容)并且没有起作用。

  • cascade = CascadeType.PERSIST(现在我保留了两个对象,否则会收到“未标记的层叠PERSIST”错误)]
  • 正在删除生成值ID
  • 没有OneToMany(城市内部)声明
  • 仅使用不带任何特定声明(例如fetchtype)的ManyToOne
  • 没有join.column

这就是我所记得的。如果您需要更多信息,请告诉我。

编辑:

我从网络服务获取天气数据。

我的WeatherReader:

public class WeatherReader extends RESTReader {


    private RESTReader client = new RESTReader();

    public List<Weather> getAllWeatherData() {

        try {
            ObjectMapper mapper = new ObjectMapper();
            List<City> citiesToBeCalled = client.deserialize(); // list resulting from deserialization
            ArrayList<List<Weather>> allWeatherList = new ArrayList<>();
            for (int i = 0; i < 1; i++) { //TODO: replace 1 with citiesToBeCalled.size() to have all cities
                String json = client.weatherData(citiesToBeCalled.get(i).getCityName());
                List<RawWeatherData> rawWeatherList = Arrays.asList(mapper.readValue(json, RawWeatherData[].class));

                List<Weather> weatherList = new ArrayList<>();

                for (int j = 0; j < rawWeatherList.size(); j++){
                    weatherList.add(rawWeatherList.get(j).convertToWeather());
                }

                allWeatherList.add(weatherList);
            }
            return allWeatherList.stream().flatMap(x -> x.stream()).collect(Collectors.toList());
        } catch (Exception e) {
            System.out.println("Error:" + e.getMessage());
            return null;
        }
    }
}

我的RestReader.class:

public class RESTReader {

    private String masterDataCityFilePath = "t.tmp";
    private static final String BASE_URI = "removed due to privacy";
    private HttpClient httpClient = HttpClient.newHttpClient();
    private String mimeType = "application/json";

    //TODO: this is already good and can be used for the CityReader
    public String allCitiesAsJson() throws Exception {

        HttpRequest req = HttpRequest.newBuilder(URI.create(BASE_URI + "cities")).headers("Accept", mimeType).GET().build();
        System.out.println("REQUEST SENT:" + req);
        HttpResponse<String> res = httpClient.send(req, HttpResponse.BodyHandlers.ofString());

        if (res.statusCode() == 200) {
            return res.body().toString();
        } else {
            throw new Exception("Status-code:" + res.statusCode());
        }
    }

    public String weatherData(String cityname) throws Exception{


        String realcityname = cityname.replace(" ", "%20");

        HttpRequest req = HttpRequest.newBuilder(URI.create(BASE_URI + realcityname)).headers("Accept", mimeType).GET().build();
        System.out.println("REQUEST SENT:" + req);
        HttpResponse<String> res = httpClient.send(req, HttpResponse.BodyHandlers.ofString());

        if (res.statusCode() == 200) {
            return res.body().toString();
        } else {
            throw new Exception("Status-code:" + res.statusCode());
        }
    }

    public void serialize(List<City> cityList) { //Creating
        try {
            FileOutputStream fileOut = new FileOutputStream(masterDataCityFilePath); //(MasterdataCities)
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(cityList);
            out.close();
            fileOut.close();
            System.out
                    .println("Master data file saved under: " + masterDataCityFilePath);
        } catch (IOException i) {
            System.err.println("There was an error saving the file!");
            System.err.println("Wrong directory?");
            i.printStackTrace();
        }
    }

    public List<City> deserialize() {
        try {
            FileInputStream fileIn = new FileInputStream(masterDataCityFilePath);
            ObjectInputStream in = new ObjectInputStream(fileIn);
            List<City> cityList = (List<City>) in.readObject();

            in.close();
            System.out
                    .println("Loaded cities from: " + masterDataCityFilePath);

            return cityList;
        } catch (IOException | ClassNotFoundException e) {
            System.err.println("There was an error loading from:" + masterDataCityFilePath);
            System.err.println("Wrong directory?\n");
            System.out.println("Directory is: " + masterDataCityFilePath);
            e.printStackTrace();
        }
        return null;
    }

    public String getMasterDataCityFilePath() {
        return masterDataCityFilePath;
    }

    public void setMasterDataCityFilePath(String masterDataCityFilePath) {
        this.masterDataCityFilePath = masterDataCityFilePath;
    }
}
java database persistence many-to-one persist
2个回答
0
投票

删除这段代码:

@OneToMany(mappedBy = "city")
private List<Weather> weather;

我相信City类中的此映射还将数据写入您的db表中。对于ManyToOne联接,以一种方式进行映射就足够了。比较这些文件:https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/ManyToOne.htmlhttps://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/OneToMany.html

希望有帮助。


0
投票

显示在其中创建Weather实例的代码,应该是问题所在。问题中显示的代码并不能决定数据的方式。相反,他们告诉JPA:嘿,jpa,请创建一个新事务,将这些对象状态转换为适当的SQL INSERT QUERY,然后执行它们。因此,决定您在DB中的数据是在调用EntityManager持久化对象之前的对象状态。

© www.soinside.com 2019 - 2024. All rights reserved.