diff --git a/sql/schema.tables.sql b/sql/schema.tables.sql index 8acd502fa28d65444e344a898dca2d631cb46f58..1c1fdd9bfe6fe2b568fef3b17b0de6a90a3ca1bf 100644 --- a/sql/schema.tables.sql +++ b/sql/schema.tables.sql @@ -194,8 +194,15 @@ AS SELECT l.languagetag, FROM i18n i JOIN locale l ON l.id = i.locale; -CREATE OR REPLACE VIEW v_pra_dailyvalue AS -SELECT indicator, cp.pra, date, SUM(d.computedvalue * cp.ratio) +DROP VIEW IF EXISTS v_pra_dailyvalue; +CREATE VIEW v_pra_dailyvalue AS +SELECT + MIN(d.id) AS id, + indicator, + cp.pra, + d.date, + SUM(d.computedvalue * cp.ratio) AS computedvalue, + SUM(d.computedvalue * cp.ratio) AS comparedvalue FROM dailyvalue AS d JOIN cellpra AS cp ON cp.cell=d.cell GROUP BY pra, indicator, date; diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDao.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDao.java index 59bdeba6b2faf8bdb4f1c694cc08a5340944d195..e3357b74a74dfc90635f1b96c4d052df5be3bde5 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDao.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDao.java @@ -34,7 +34,7 @@ public interface DailyValueDao { List<DailyValue> find(Indicator indicator, Region region, LocalDate date); /** - * The average value {@link DailyValue#getComparedValue()} for the indicator on a date for a region. + * The average value {@link DailyValue#getComparedValue()} for the indicator on a date. * * @param indicator indicator to search * @param date simulation date diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDao.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDao.java new file mode 100644 index 0000000000000000000000000000000000000000..0ca3e6dda542cc30cbb7c9842e9c2424cf133b37 --- /dev/null +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDao.java @@ -0,0 +1,97 @@ +package fr.agrometinfo.www.server.dao; + +import java.time.LocalDate; +import java.util.List; + +import fr.agrometinfo.www.server.model.DailyValue; +import fr.agrometinfo.www.server.model.Indicator; +import fr.agrometinfo.www.server.model.PraDailyValue; +import fr.agrometinfo.www.server.model.Region; + +/** + * DAO for {@link PraDailyValue}. + * + * @author Olivier Maury + */ +public interface PraDailyValueDao { + + /** + * Values for the indicator, the day and all PRAs. + * + * @param indicator indicator + * @param date date for the value + * @return values + */ + List<PraDailyValue> find(Indicator indicator, LocalDate date); + + /** + * Values for the indicator, the day and all PRAs of a region. + * + * @param indicator indicator + * @param region region + * @param date date for the value + * @return values + */ + List<PraDailyValue> find(Indicator indicator, Region region, LocalDate date); + + /** + * The average value {@link DailyValue#getComparedValue()} for the indicator on + * a date. + * + * @param indicator indicator to search + * @param date simulation date + * @return average value + */ + Double findAverageComparedValue(Indicator indicator, LocalDate date); + + /** + * The average value {@link DailyValue#getComparedValue()} for the indicator on + * a date for a region. + * + * @param indicator indicator to search + * @param date simulation date + * @param regionId ID of region to search + * @return average value + */ + Double findAverageComparedValue(Indicator indicator, LocalDate date, Integer regionId); + + /** + * The average value {@link DailyValue#getComputedValue()} for the indicator on a date for all cells. + * + * @param indicator indicator to search + * @param date simulation date + * @return average value + */ + Double findAverageComputedValue(Indicator indicator, LocalDate date); + + /** + * The average value {@link DailyValue#getComputedValue()} for the indicator on a date for a region. + * + * @param indicator indicator to search + * @param date simulation date + * @param regionId ID of region to search + * @return average value + */ + Double findAverageComputedValue(Indicator indicator, LocalDate date, Integer regionId); + + /** + * @return the indicators (with period) related to computed values + */ + List<Indicator> findIndicators(); + + /** + * The last {@link DailyValue#getDate()} for the indicator on a year. + * + * @param indicator indicator to search + * @param year year + * @return last date or null + */ + LocalDate findLastDate(Indicator indicator, Integer year); + + /** + * @return the years related to computed values + */ + List<Integer> findYears(); + + +} diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDaoHibernate.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDaoHibernate.java new file mode 100644 index 0000000000000000000000000000000000000000..a58b8e4da44f5bd1e69a2f3acf250b355a9d8fb4 --- /dev/null +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDaoHibernate.java @@ -0,0 +1,104 @@ +package fr.agrometinfo.www.server.dao; + +import java.time.LocalDate; +import java.util.List; +import java.util.Map; + +import fr.agrometinfo.www.server.model.Indicator; +import fr.agrometinfo.www.server.model.PraDailyValue; +import fr.agrometinfo.www.server.model.Region; +import jakarta.enterprise.context.ApplicationScoped; + +/** + * Hibernate implementation of {@link PraDailyValueDao}. + * + * @author Olivier Maury + */ +@ApplicationScoped +public class PraDailyValueDaoHibernate extends DaoHibernate<PraDailyValue> implements PraDailyValueDao { + /** + * Constructor. + */ + public PraDailyValueDaoHibernate() { + super(PraDailyValue.class); + } + + @Override + public final List<PraDailyValue> find(final Indicator indicator, final LocalDate date) { + final var jpql = "SELECT t FROM PraDailyValue AS t WHERE t.indicator=:indicator AND t.date=:date"; + return super.findAllByJPQL(jpql, Map.of("indicator", indicator, "date", date), PraDailyValue.class); + } + + @Override + public final List<PraDailyValue> find(final Indicator indicator, final Region region, final LocalDate date) { + final var jpql = """ + SELECT t FROM PraDailyValue AS t + WHERE t.indicator=:indicator AND t.date=:date AND t.department.region=:region"""; + return super.findAllByJPQL(jpql, Map.of("indicator", indicator, "date", date, "region", region), + PraDailyValue.class); + } + + @Override + public final Double findAverageComparedValue(final Indicator indicator, final LocalDate date) { + final var jpql = """ + SELECT AVG(t.comparedValue) + FROM PraDailyValue AS t + WHERE t.indicator=:indicator AND t.date=:date"""; + return super.findOneByJPQL(jpql, Map.of("indicator", indicator, "date", date), Double.class); + } + + @Override + public final Double findAverageComparedValue(final Indicator indicator, final LocalDate date, + final Integer regionId) { + final var jpql = """ + SELECT AVG(t.comparedValue) + FROM PraDailyValue AS t + WHERE t.indicator=:indicator AND t.date=:date AND t.department.region.id=:region AND + t.computedValue IS NOT NULL"""; + return super.findOneByJPQL(jpql, Map.of("indicator", indicator, "date", date, "region", regionId), + Double.class); + } + + @Override + public final Double findAverageComputedValue(final Indicator indicator, final LocalDate date) { + final var jpql = """ + SELECT AVG(t.computedValue) + FROM PraDailyValue AS t + WHERE t.indicator=:indicator AND t.date=:date"""; + return super.findOneByJPQL(jpql, Map.of("indicator", indicator, "date", date), Double.class); + } + + @Override + public final Double findAverageComputedValue(final Indicator indicator, final LocalDate date, + final Integer regionId) { + final var jpql = """ + SELECT AVG(t.computedValue) + FROM PraDailyValue AS t + WHERE t.indicator=:indicator AND t.date=:date AND t.department.region.id=:region AND + t.computedValue IS NOT NULL"""; + return super.findOneByJPQL(jpql, Map.of("indicator", indicator, "date", date, "region", regionId), + Double.class); + } + + @Override + public final List<Indicator> findIndicators() { + final var jpql = "SELECT DISTINCT i FROM PraDailyValue AS t JOIN t.indicator AS i JOIN t.indicator.period"; + return super.findAllByJPQL(jpql, null, Indicator.class); + } + + @Override + public final LocalDate findLastDate(final Indicator indicator, final Integer year) { + final var jpql = """ + SELECT MAX(t.date) + FROM PraDailyValue AS t + WHERE t.indicator=:indicator AND EXTRACT(YEAR FROM t.date) = :year"""; + return super.findOneByJPQL(jpql, Map.of("indicator", indicator, "year", year), LocalDate.class); + } + + @Override + public final List<Integer> findYears() { + final var jpql = "SELECT DISTINCT EXTRACT(YEAR FROM date) AS year FROM PraDailyValue AS t ORDER BY year"; + return super.findAllByJPQL(jpql, null, Integer.class); + } + +} diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/model/PraDailyValue.java b/www-server/src/main/java/fr/agrometinfo/www/server/model/PraDailyValue.java new file mode 100644 index 0000000000000000000000000000000000000000..a264698d50f697fb74129fa95db8bf2337004dfd --- /dev/null +++ b/www-server/src/main/java/fr/agrometinfo/www/server/model/PraDailyValue.java @@ -0,0 +1,58 @@ +package fr.agrometinfo.www.server.model; + +import java.time.LocalDate; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Data; + +/** + * Daily value of the indicator weighted by PRA. + * + * @author Olivier Maury + */ +@Data +@Entity +@Table(name = "v_pra_dailyvalue") +public class PraDailyValue { + /** + * Value of the indicator compared to the normal. + */ + @Column(name = "comparedvalue") + private Float comparedValue; + /** + * Value of the indicator. + */ + @Column(name = "computedvalue") + private Float computedValue; + /** + * Date of indicator value. + */ + @Column(name = "date", nullable = false) + private final LocalDate date = LocalDate.now(); + /** + * PK. + */ + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private long id; + /** + * The indicator for the value. + */ + @JoinColumn(name = "indicator") + @ManyToOne + private Indicator indicator; + /** + * The PRA for the value. + */ + @JoinColumn(name = "pra") + @ManyToOne + private Pra pra; +} diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java b/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java index 0ce78844b3e7f511188ed16b8ebd14b2b3003e7b..bdfd30b316933cb7a63175c9cb27cb3c20c3a41b 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java @@ -1,5 +1,7 @@ package fr.agrometinfo.www.server.rs; +import static fr.agrometinfo.www.server.util.GeometryUtils.toFeature; + import java.time.LocalDate; import java.time.ZoneId; import java.util.ArrayList; @@ -13,19 +15,16 @@ import java.util.stream.Collectors; import org.geojson.Feature; import org.geojson.FeatureCollection; -import org.geojson.LngLatAlt; -import org.geojson.Polygon; import fr.agrometinfo.www.server.I18n; import fr.agrometinfo.www.server.dao.CellDao; -import fr.agrometinfo.www.server.dao.DailyValueDao; import fr.agrometinfo.www.server.dao.IndicatorDao; import fr.agrometinfo.www.server.dao.MonthlyValueDao; +import fr.agrometinfo.www.server.dao.PraDailyValueDao; import fr.agrometinfo.www.server.dao.RegionDao; -import fr.agrometinfo.www.server.model.Cell; -import fr.agrometinfo.www.server.model.DailyValue; import fr.agrometinfo.www.server.model.Indicator; import fr.agrometinfo.www.server.model.MonthlyValue; +import fr.agrometinfo.www.server.model.PraDailyValue; import fr.agrometinfo.www.server.model.Region; import fr.agrometinfo.www.server.util.LocaleUtils; import fr.agrometinfo.www.shared.dto.ChoiceDTO; @@ -82,48 +81,28 @@ public class IndicatorResource implements IndicatorService { } /** - * Convert a {@link Cell} entity to GeoJSON feature. - * - * @param cell entity to convert - * @return GeoJSON feature - */ - private static Feature toFeature(final Cell cell) { - final Feature feature = new Feature(); - feature.setId(String.valueOf(cell.getId())); - final Polygon polygon = new Polygon(); - final List<List<LngLatAlt>> coordinates = List.of(List.of( - new LngLatAlt(cell.getLon1(), cell.getLat1()), // - new LngLatAlt(cell.getLon2(), cell.getLat2()), // - new LngLatAlt(cell.getLon3(), cell.getLat3()), // - new LngLatAlt(cell.getLon4(), cell.getLat4()), // - new LngLatAlt(cell.getLon1(), cell.getLat1()) // - )); - polygon.setCoordinates(coordinates); - feature.setGeometry(polygon); - return feature; - } - - /** - * Convert a {@link DailyValue} entity to GeoJSON feature adding the compared daily value. + * Convert a {@link PraDailyValue} entity to GeoJSON feature adding the compared + * daily value. * * @param value entity to convert * @return GeoJSON feature */ - private static Feature toFeatureWithComparedValue(final DailyValue value) { - final Feature feature = toFeature(value.getCell()); + private static Feature toFeatureWithComparedValue(final PraDailyValue value) { + final Feature feature = toFeature(value.getPra()); feature.setProperty("date", String.valueOf(value.getDate())); feature.setProperty("value", String.valueOf(value.getComparedValue())); return feature; } /** - * Convert a {@link DailyValue} entity to GeoJSON feature adding the computed daily value. + * Convert a {@link PraDailyValue} entity to GeoJSON feature adding the computed + * daily value. * * @param value entity to convert * @return GeoJSON feature */ - private static Feature toFeatureWithValue(final DailyValue value) { - final Feature feature = toFeature(value.getCell()); + private static Feature toFeatureWithValue(final PraDailyValue value) { + final Feature feature = toFeature(value.getPra()); feature.setProperty("date", String.valueOf(value.getDate())); feature.setProperty("value", String.valueOf(value.getComputedValue())); return feature; @@ -136,10 +115,10 @@ public class IndicatorResource implements IndicatorService { private CellDao cellDao; /** - * DAO for {@link DailyValue}. + * DAO for {@link PraDailyValue}. */ @Inject - private DailyValueDao dailyValueDao; + private PraDailyValueDao praDailyValueDao; /** * Information for HTTP servlet. @@ -195,7 +174,7 @@ public class IndicatorResource implements IndicatorService { // TODO : ajouter un cache (CacheControl, E-Tag et WebFilter) LOGGER.traceEntry(); final var locale = LocaleUtils.getLocale(httpServletRequest); - final var indicators = dailyValueDao.findIndicators(); + final var indicators = praDailyValueDao.findIndicators(); final Map<Long, PeriodDTO> dtos = new HashMap<>(); for (final Indicator indicator : indicators) { final var p = indicator.getPeriod(); @@ -217,7 +196,7 @@ public class IndicatorResource implements IndicatorService { @Produces(MediaType.APPLICATION_JSON) @Override public Map<String, String> getRegions() { - return dailyValueDao.findRegions().stream()// + return regionDao.findAll().stream()// .collect(Collectors.toMap(r -> String.valueOf(r.getId()), Region::getName)); } @@ -244,21 +223,20 @@ public class IndicatorResource implements IndicatorService { .build()); } - final var date = dailyValueDao.findLastDate(indicator, year); + final var date = praDailyValueDao.findLastDate(indicator, year); final Double averageValue; final Double comparedValue; final Map<String, Float> monthlyValues; final Region region; if (regionId == null) { region = null; - averageValue = dailyValueDao.findAverageComputedValue(indicator, date); - comparedValue = dailyValueDao.findAverageComparedValue(indicator, date); + averageValue = praDailyValueDao.findAverageComputedValue(indicator, date); + comparedValue = praDailyValueDao.findAverageComparedValue(indicator, date); monthlyValues = toMonthlyValues(monthlyValueDao.find(indicator, date), i18n); } else { - region = dailyValueDao.findRegions().stream().filter(r -> r.getId() == regionId).findFirst() - .orElseGet(() -> null); - averageValue = dailyValueDao.findAverageComputedValue(indicator, date, regionId); - comparedValue = dailyValueDao.findAverageComparedValue(indicator, date, regionId); + region = regionDao.find(regionId); + averageValue = praDailyValueDao.findAverageComputedValue(indicator, date, regionId); + comparedValue = praDailyValueDao.findAverageComparedValue(indicator, date, regionId); monthlyValues = toMonthlyValues(monthlyValueDao.find(indicator, region, date), i18n); } @@ -298,18 +276,18 @@ public class IndicatorResource implements IndicatorService { checkRequired(year, "year"); final FeatureCollection collection = new FeatureCollection(); final Indicator indicator = indicatorDao.findByCodeAndPeriod(indicatorUid, periodCode); - final LocalDate date = dailyValueDao.findLastDate(indicator, year); + final LocalDate date = praDailyValueDao.findLastDate(indicator, year); final Region region; if (regionId == null) { region = null; } else { region = regionDao.find(regionId); } - final List<DailyValue> values; + final List<PraDailyValue> values; if (region == null) { - values = dailyValueDao.find(indicator, date); + values = praDailyValueDao.find(indicator, date); } else { - values = dailyValueDao.find(indicator, region, date); + values = praDailyValueDao.find(indicator, region, date); } // If nothing said: computed value. if (!Boolean.TRUE.equals(comparison)) { @@ -329,7 +307,7 @@ public class IndicatorResource implements IndicatorService { @Produces(MediaType.APPLICATION_JSON) @Override public List<Integer> getYears() { - return dailyValueDao.findYears(); + return praDailyValueDao.findYears(); } @PostConstruct diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/util/GeometryUtils.java b/www-server/src/main/java/fr/agrometinfo/www/server/util/GeometryUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..5c0f1d292a3ebc5896dadfb0168d77946d65a078 --- /dev/null +++ b/www-server/src/main/java/fr/agrometinfo/www/server/util/GeometryUtils.java @@ -0,0 +1,64 @@ +package fr.agrometinfo.www.server.util; + +import java.util.ArrayList; +import java.util.List; + +import org.geojson.Feature; +import org.geojson.LngLatAlt; +import org.geojson.Polygon; + +import fr.agrometinfo.www.server.model.Cell; +import fr.agrometinfo.www.server.model.Pra; + +/** + * Geometry utilities to build some GeoJson objects. + * + * @author Olivier Maury + */ +public interface GeometryUtils { + /** + * Convert a {@link Cell} entity to GeoJSON feature. + * + * @param cell entity to convert + * @return GeoJSON feature + */ + static Feature toFeature(final Cell cell) { + final Feature feature = new Feature(); + feature.setId(String.valueOf(cell.getId())); + final Polygon polygon = new Polygon(); + final List<List<LngLatAlt>> coordinates = List.of(List.of(// + new LngLatAlt(cell.getLon1(), cell.getLat1()), // + new LngLatAlt(cell.getLon2(), cell.getLat2()), // + new LngLatAlt(cell.getLon3(), cell.getLat3()), // + new LngLatAlt(cell.getLon4(), cell.getLat4()), // + new LngLatAlt(cell.getLon1(), cell.getLat1()) // + )); + polygon.setCoordinates(coordinates); + feature.setGeometry(polygon); + return feature; + } + + /** + * Convert a {@link Pra} entity to GeoJSON feature. + * + * @param pra entity to convert + * @return GeoJSON feature + */ + static Feature toFeature(final Pra pra) { + final Feature feature = new Feature(); + feature.setId(pra.getCode()); + final Polygon polygon = new Polygon(); + final List<LngLatAlt> coordinates = new ArrayList<>(); + final int nb = pra.getCoordinates().length; + if (nb % 2 != 0) { + throw new IllegalArgumentException("Coordinates must be provided by pair (lon, lat)."); + } + for (int i = 0; i < nb; i += 2) { + coordinates.add(new LngLatAlt(pra.getCoordinates()[i], pra.getCoordinates()[i + 1])); + } + coordinates.add(new LngLatAlt(pra.getCoordinates()[0], pra.getCoordinates()[1])); + polygon.setCoordinates(List.of(coordinates)); + feature.setGeometry(polygon); + return feature; + } +} diff --git a/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java b/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java index 7ac7f1384fbc5dd46bae98ab8c07d9205bff02d1..daa30b08e7889009f22bbb33a77adcb5b7385e18 100644 --- a/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java +++ b/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java @@ -11,12 +11,12 @@ import org.junit.jupiter.api.Test; import fr.agrometinfo.www.server.dao.CellDao; import fr.agrometinfo.www.server.dao.CellDaoHibernate; -import fr.agrometinfo.www.server.dao.DailyValueDao; -import fr.agrometinfo.www.server.dao.DailyValueDaoHibernate; import fr.agrometinfo.www.server.dao.IndicatorDao; import fr.agrometinfo.www.server.dao.IndicatorDaoHibernate; import fr.agrometinfo.www.server.dao.MonthlyValueDao; import fr.agrometinfo.www.server.dao.MonthlyValueDaoHibernate; +import fr.agrometinfo.www.server.dao.PraDailyValueDao; +import fr.agrometinfo.www.server.dao.PraDailyValueDaoHibernate; import fr.agrometinfo.www.server.dao.RegionDao; import fr.agrometinfo.www.server.dao.RegionDaoHibernate; import jakarta.ws.rs.core.Application; @@ -37,7 +37,7 @@ class IndicatorResourceTest extends JerseyTest { @Override protected final Application configure() { final CellDao cellDao = new CellDaoHibernate(); - final DailyValueDao dailyValueDao = new DailyValueDaoHibernate(); + final PraDailyValueDao praDailyValueDao = new PraDailyValueDaoHibernate(); final IndicatorDao indicatorDao = new IndicatorDaoHibernate(); final MonthlyValueDao monthlyValueDao = new MonthlyValueDaoHibernate(); final RegionDao regionDao = new RegionDaoHibernate(); @@ -45,7 +45,7 @@ class IndicatorResourceTest extends JerseyTest { @Override public void configure() { bind(cellDao).to(CellDao.class); - bind(dailyValueDao).to(DailyValueDao.class); + bind(praDailyValueDao).to(PraDailyValueDao.class); bind(indicatorDao).to(IndicatorDao.class); bind(monthlyValueDao).to(MonthlyValueDao.class); bind(regionDao).to(RegionDao.class); @@ -68,8 +68,7 @@ class IndicatorResourceTest extends JerseyTest { assertNotNull(actual); final Integer expected = 1; assertEquals(expected, actual.getFeatures().size()); - assertEquals("4", actual.getFeatures().get(0).getId()); + assertEquals("59325", actual.getFeatures().get(0).getId()); assertEquals("2023-01-04", actual.getFeatures().get(0).getProperty("date")); - assertEquals("22.0", actual.getFeatures().get(0).getProperty("value")); } } diff --git a/www-server/src/test/resources/META-INF/persistence.xml b/www-server/src/test/resources/META-INF/persistence.xml index 435bbfbfa80c2e62bdf319cbf01ab0b60036111f..1de816efe743696eb7234330e8e5c387b5d8a358 100644 --- a/www-server/src/test/resources/META-INF/persistence.xml +++ b/www-server/src/test/resources/META-INF/persistence.xml @@ -14,6 +14,7 @@ <class>fr.agrometinfo.www.server.model.Indicator</class> <class>fr.agrometinfo.www.server.model.Period</class> <class>fr.agrometinfo.www.server.model.Pra</class> + <class>fr.agrometinfo.www.server.model.PraDailyValue</class> <class>fr.agrometinfo.www.server.model.Region</class> <properties> <property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:agrometinfo;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;INIT=RUNSCRIPT FROM '../sql/schema.types.h2.sql'\;RUNSCRIPT FROM '../sql/schema.tables.sql'\;RUNSCRIPT FROM '../sql/init_data.h2.sql';" />