gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 20:05:37 29 4
gpt4 key购买 nike

我得到了城市和天气。天气应该指向数据库中的城市对象。一个城市可以有多个天气条目。我的问题是,每次我向数据库添加天气时,它都会创建一个具有相同名称但具有其他 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;

}

我的餐 table 天气:

enter image description here

我的表城市:(目前我的天气数据仅来自这一个城市,没错)

enter image description here

这里列出了我迄今为止尝试过的(至少是我能记得的)但没有成功的内容。

  • cascade = CascadeType.PERSIST(现在我保留这两个对象,否则我会收到“未标记级联 PERSIST”错误)
  • 删除生成值 ID
  • 没有 OneToMany(城市内)声明
  • 仅使用 ManyToOne,无需任何特定声明(如 fetchtype)
  • 没有 join.column

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

编辑:

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

我的天气阅读器:

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 because of privacy reasons";
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;
}
}

编辑2:我的convertToWeather();

    public Weather convertToWeather(){
try {
Weather weather = new Weather();
weather.setCity(city);

String str = lastUpdateTime;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
weather.setTimeStamp(dateTime);

//assign wind speed
String datacontent[] = data.split("#");

String windSpeedValue[] = datacontent[12].split(":", 2); // specify data content number
if (windSpeedValue[1].equals("unknown")){
weather.setWindSpeed(null);
} else {
weather.setWindSpeed(Float.parseFloat(windSpeedValue[1])); //general just gimme the value specifier
}

//assign wind direction
String windDirValue[] = datacontent[13].split(":", 2); // specify data content number
if (windDirValue[1].equals("unknown")){
weather.setWindDir(null);
} else {
weather.setWindDir(Float.parseFloat(windDirValue[1])); //general just gimme the value specifier
}

//assign humidity
String humidityValue[] = datacontent[11].split(":", 2); // specify data content number
if (humidityValue[1].equals("unknown")){
weather.setHumidity(null);
} else {
weather.setHumidity(Float.parseFloat(humidityValue[1])); //general just gimme the value specifier
}

//assign temperature
String temperatureValue[] = datacontent[9].split(":", 2); // specify data content number
if (temperatureValue[1].equals("unknown")){
weather.setTemperature(null);
} else {
weather.setTemperature(Float.parseFloat(temperatureValue[1])); //general just gimme the value specifier
}

//assign description
String descriptionValue[] = datacontent[8].split(":", 2); // specify data content number
if (descriptionValue[1].equals("unknown")){
weather.setWeatherDescription("unknown");
} else {
weather.setWeatherDescription(descriptionValue[1]); //general just gimme the value specifier
}

return weather;

} catch (Exception e) {
System.out.println("Error:" + e.toString());
return null;
}
}

最佳答案

问题很简单,对于JPA来说,如果你的实体没有任何ID,那么这意味着如果ID为空,它将执行INSERT,如果ID不为空,它将执行UPDATE。

据我所知,您的城市实例始终是一个新对象,或者至少是一个在持久性上下文中未处理的对象。

在您的代码中,您应该首先检查数据库中是否已有指定城市,如果是,请将其附加到您的天气中。如果不只是插入它(就像您在 SQL 中所做的那样...)

为了避免奇怪的行为,我还可以建议您对城市名称添加唯一约束。

如果它解决了您的问题,请告诉我

关于java - ManyToOne 在两个表中为每个新对象创建新条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58985605/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com