我有城市和天气。天气应指向数据库中的城市对象。一个城市可以有多个天气条目。我的问题是,每次向数据库添加天气时,都会创建一个具有相同名称但其他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;
}
我的餐桌天气:
我的餐桌城市:(目前我的天气数据仅来自这个城市,是的)
我现在真的在搜索任何东西,我有点无助。这里列出了我到目前为止尝试过的内容(至少我能记住的所有内容)并且没有起作用。
这就是我所记得的。如果您需要更多信息,请告诉我。
编辑:
我从网络服务获取天气数据。
我的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;
}
}
删除这段代码:
@OneToMany(mappedBy = "city")
private List<Weather> weather;
我相信City类中的此映射还将数据写入您的db表中。对于ManyToOne联接,以一种方式进行映射就足够了。比较这些文件:https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/ManyToOne.html和https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/OneToMany.html
希望有帮助。
显示在其中创建Weather实例的代码,应该是问题所在。问题中显示的代码并不能决定数据的方式。相反,他们告诉JPA:嘿,jpa,请创建一个新事务,将这些对象状态转换为适当的SQL INSERT QUERY,然后执行它们。因此,决定您在DB中的数据是在调用EntityManager持久化对象之前的对象状态。