diff --git a/src/main/java/info/peper/vz/rest/Calculator.java b/src/main/java/info/peper/vz/rest/Calculator.java new file mode 100644 index 0000000..7b0d518 --- /dev/null +++ b/src/main/java/info/peper/vz/rest/Calculator.java @@ -0,0 +1,153 @@ +package info.peper.vz.rest; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.LinkedList; +import java.util.List; + +import info.peper.vz.rest.bo.db.Aggregate2; + +public final class Calculator { + + public static List processHouseMulti(final int houseId, + final long startTimestamp, + final long endTimestamp, + final long interval, + final int[] channelIdsSolar, + final int[] channelIdsMeter, + final Connection con) throws SQLException { + final List result = new LinkedList(); + + final PreparedStatement[] stmtSolar = new PreparedStatement[channelIdsSolar.length]; + final PreparedStatement[] stmtMeter = new PreparedStatement[channelIdsMeter.length]; + final ResultSet[] rsSolar = new ResultSet[channelIdsSolar.length]; + final ResultSet[] rsMeter = new ResultSet[channelIdsMeter.length]; + long[] currentTsSolar = new long[channelIdsSolar.length]; + long[] currentTsMeter = new long[channelIdsMeter.length]; + boolean[] noNextRecordSolar = new boolean[channelIdsSolar.length]; + boolean[] noNextRecordMeter = new boolean[channelIdsMeter.length]; + + for (int i = 0; i < channelIdsSolar.length; i++) { + stmtSolar[i] = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;"); + stmtSolar[i].setInt(1, channelIdsSolar[i]); + stmtSolar[i].setLong(2, startTimestamp); + stmtSolar[i].setFetchSize(1000); + rsSolar[i] = stmtSolar[i].executeQuery(); + currentTsSolar[i] = startTimestamp; + noNextRecordSolar[i] = false; + } + + for (int i = 0; i < channelIdsMeter.length; i++) { + stmtMeter[i] = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;"); + stmtMeter[i].setInt(1, channelIdsMeter[i]); + stmtMeter[i].setLong(2, startTimestamp); + stmtMeter[i].setFetchSize(1000); + rsMeter[i] = stmtMeter[i].executeQuery(); + currentTsMeter[i] = startTimestamp; + noNextRecordMeter[i] = false; + } + + System.out.println("Starting..."); + long intervalProduced = 0; + long intervalObtained = 0; + long intervalInjected = 0; + + long intervalStartTimestamp = startTimestamp; + long intervalEndTimestamp = startTimestamp + interval; + + // Eigentliche Verarbeitung + + while (getMinOfArray(currentTsSolar) <= endTimestamp || getMinOfArray(currentTsMeter) <= endTimestamp) { + System.out.print(intervalStartTimestamp + ": "); + + for (int iSolar = 0; iSolar < channelIdsSolar.length; iSolar++) { + currentTsSolar[iSolar] = intervalStartTimestamp; + + while (currentTsSolar[iSolar] < intervalEndTimestamp && (noNextRecordSolar[iSolar] || rsSolar[iSolar].next())) { + if (noNextRecordSolar[iSolar]) { + noNextRecordSolar[iSolar] = false; + } + + final long tsSolar = rsSolar[iSolar].getLong("timestamp"); + final double value = rsSolar[iSolar].getDouble("value") > 1.0 ? rsSolar[iSolar].getDouble("value") : 0.0; + final long tsDiff = (tsSolar < intervalEndTimestamp) ? tsSolar - currentTsSolar[iSolar] : intervalEndTimestamp - currentTsSolar[iSolar]; + + currentTsSolar[iSolar] = tsSolar; + + intervalProduced += Math.round(value * tsDiff); + + if (currentTsSolar[iSolar] >= intervalEndTimestamp) { + noNextRecordSolar[iSolar] = true; + } + System.out.print("."); + } + } + + double meterValue = 0; + for (int iMeter = 0; iMeter < channelIdsMeter.length; iMeter++) { + currentTsMeter[iMeter] = intervalStartTimestamp; + + while (currentTsMeter[iMeter] < intervalEndTimestamp && (noNextRecordMeter[iMeter] || rsMeter[iMeter].next())) { + if (noNextRecordMeter[iMeter]) { + noNextRecordMeter[iMeter] = false; + } + final long tsMeter = rsMeter[iMeter].getLong("timestamp"); + final double value = rsMeter[iMeter].getDouble("value"); + final long tsDiff = (tsMeter < intervalEndTimestamp) ? tsMeter - currentTsMeter[iMeter] : intervalEndTimestamp - currentTsMeter[iMeter]; + + currentTsMeter[iMeter] = tsMeter; + + meterValue += Math.round(value * tsDiff); + + if (currentTsMeter[iMeter] >= intervalEndTimestamp) { + noNextRecordMeter[iMeter] = true; + } + System.out.print("#"); + } + } + if (meterValue > 0.0) { + intervalObtained += Math.round(meterValue); + } else { + intervalInjected += Math.abs(Math.round(meterValue)); + } + + System.out.println(" " + intervalProduced + " / " + intervalObtained + " / " + intervalInjected); + + result.add(new Aggregate2(houseId, intervalStartTimestamp, intervalEndTimestamp, intervalProduced, intervalObtained, intervalInjected)); + + intervalStartTimestamp += interval; + intervalEndTimestamp += interval; + + intervalInjected = 0; + intervalObtained = 0; + intervalProduced = 0; + } + + // Aufräumen + for (int i = 0; i < channelIdsSolar.length; i++) { + rsSolar[i].close(); + stmtSolar[i].close(); + } + + for (int i = 0; i < channelIdsMeter.length; i++) { + rsMeter[i].close(); + stmtMeter[i].close(); + } + + return result; + } + + private static long getMinOfArray(final long[] input) { + long result = Long.MAX_VALUE; + for (long i : input) { + if (i < result) { + result = i; + } + } + return result; + } + + +} diff --git a/src/main/java/info/peper/vz/rest/FillAggregateTableMain3.java b/src/main/java/info/peper/vz/rest/FillAggregateTableMain3.java index ba21ea4..e8602e9 100644 --- a/src/main/java/info/peper/vz/rest/FillAggregateTableMain3.java +++ b/src/main/java/info/peper/vz/rest/FillAggregateTableMain3.java @@ -8,14 +8,12 @@ import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.time.Instant; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAccessor; -import java.util.LinkedList; import java.util.List; import info.peper.vz.rest.bo.db.Aggregate2; @@ -38,7 +36,14 @@ public class FillAggregateTableMain3 { final long startTimeStamp = getTimestamp("2022-05-20T09:00:00"); final long finalEndTimeStamp = getTimestamp("2025-03-09T15:00:00"); - final List aggregates = processHouse(1, startTimeStamp, finalEndTimeStamp, 60*1000, 4, 1, con); + final List aggregates = Calculator.processHouseMulti( + 1, + startTimeStamp, + finalEndTimeStamp, + 60*1000, + new int[] {4}, + new int[] {1}, + con); saveValues(con, aggregates, 1); } @@ -46,244 +51,17 @@ public class FillAggregateTableMain3 { final long startTimeStamp = getTimestamp("2024-06-23T17:00:00"); final long finalEndTimeStamp = getTimestamp("2025-03-09T15:00:00"); - final List aggregates = processHouseMulti(2, startTimeStamp, finalEndTimeStamp, 60*1000, new int[] {24}, new int[] {18, 19, 20}, con); + final List aggregates = Calculator.processHouseMulti( + 2, + startTimeStamp, + finalEndTimeStamp, + 60*1000, + new int[] {24}, + new int[] {18, 19, 20}, + con); saveValues(con, aggregates, 2); } - private static List processHouse(final int houseId, - final long startTimestamp, - final long endTimestamp, - final long interval, - final int channelIdSolar, - final int channelIdMeter, - final Connection con) throws SQLException { - final List result = new LinkedList(); - try (final PreparedStatement stmtSolar = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;"); - final PreparedStatement stmtMeter = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;");) { - stmtSolar.setInt(1, channelIdSolar); - stmtSolar.setLong(2, startTimestamp); - stmtSolar.setFetchSize(1000); - stmtMeter.setInt(1, channelIdMeter); - stmtMeter.setLong(2, startTimestamp); - stmtMeter.setFetchSize(1000); - - try (final ResultSet rsSolar = stmtSolar.executeQuery(); final ResultSet rsMeter = stmtMeter.executeQuery()) { - System.out.println("Starting..."); - long intervalProduced = 0; - long intervalObtained = 0; - long intervalInjected = 0; - - long currentTsSolar = startTimestamp; - long currentTsMeter = startTimestamp; - - long intervalStartTimestamp = startTimestamp; - long intervalEndTimestamp = startTimestamp + interval; - - boolean noNextRecordSolar = false; - boolean noNextRecordMeter = false; - - while (currentTsSolar <= endTimestamp || currentTsMeter <= endTimestamp) { - - currentTsSolar = intervalStartTimestamp; - currentTsMeter = intervalStartTimestamp; - - System.out.print(intervalStartTimestamp + ": "); - - while (currentTsSolar < intervalEndTimestamp && (noNextRecordSolar || rsSolar.next())) { - if (noNextRecordSolar) { - noNextRecordSolar = false; - } - - final long tsSolar = rsSolar.getLong("timestamp"); - final double value = rsSolar.getDouble("value") > 1.0 ? rsSolar.getDouble("value") : 0.0; - final long tsDiff = (tsSolar < intervalEndTimestamp) ? tsSolar - currentTsSolar : intervalEndTimestamp - currentTsSolar; - - currentTsSolar = tsSolar; - - intervalProduced += Math.round(value * tsDiff); - - if (currentTsSolar >= intervalEndTimestamp) { - noNextRecordSolar = true; - } - System.out.print("."); - } - - while (currentTsMeter < intervalEndTimestamp && (noNextRecordMeter || rsMeter.next())) { - if (noNextRecordMeter) { - noNextRecordMeter = false; - } - final long tsMeter = rsMeter.getLong("timestamp"); - final double value = rsMeter.getDouble("value"); - final long tsDiff = (tsMeter < intervalEndTimestamp) ? tsMeter - currentTsMeter : intervalEndTimestamp - currentTsMeter; - - currentTsMeter = tsMeter; - - if (value > 0.0) { - intervalObtained += Math.round(value * tsDiff); - } else { - intervalInjected += Math.abs(Math.round(value * tsDiff)); - } - - if (currentTsMeter >= intervalEndTimestamp) { - noNextRecordMeter = true; - } - System.out.print("#"); - } - - System.out.println(" " + intervalProduced + " / " + intervalObtained + " / " + intervalInjected); - - result.add(new Aggregate2(houseId, intervalStartTimestamp, intervalEndTimestamp, intervalProduced, intervalObtained, intervalInjected)); - - intervalStartTimestamp += interval; - intervalEndTimestamp += interval; - - intervalInjected = 0; - intervalObtained = 0; - intervalProduced = 0; - } - } - } - return result; - } - - private static List processHouseMulti(final int houseId, - final long startTimestamp, - final long endTimestamp, - final long interval, - final int[] channelIdsSolar, - final int[] channelIdsMeter, - final Connection con) throws SQLException { - final List result = new LinkedList(); - - final PreparedStatement[] stmtSolar = new PreparedStatement[channelIdsSolar.length]; - final PreparedStatement[] stmtMeter = new PreparedStatement[channelIdsMeter.length]; - final ResultSet[] rsSolar = new ResultSet[channelIdsSolar.length]; - final ResultSet[] rsMeter = new ResultSet[channelIdsMeter.length]; - long[] currentTsSolar = new long[channelIdsSolar.length]; - long[] currentTsMeter = new long[channelIdsMeter.length]; - boolean[] noNextRecordSolar = new boolean[channelIdsSolar.length]; - boolean[] noNextRecordMeter = new boolean[channelIdsMeter.length]; - - for (int i = 0; i < channelIdsSolar.length; i++) { - stmtSolar[i] = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;"); - stmtSolar[i].setInt(1, channelIdsSolar[i]); - stmtSolar[i].setLong(2, startTimestamp); - stmtSolar[i].setFetchSize(1000); - rsSolar[i] = stmtSolar[i].executeQuery(); - currentTsSolar[i] = startTimestamp; - noNextRecordSolar[i] = false; - } - - for (int i = 0; i < channelIdsMeter.length; i++) { - stmtMeter[i] = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;"); - stmtMeter[i].setInt(1, channelIdsMeter[i]); - stmtMeter[i].setLong(2, startTimestamp); - stmtMeter[i].setFetchSize(1000); - rsMeter[i] = stmtMeter[i].executeQuery(); - currentTsMeter[i] = startTimestamp; - noNextRecordMeter[i] = false; - } - - System.out.println("Starting..."); - long intervalProduced = 0; - long intervalObtained = 0; - long intervalInjected = 0; - - long intervalStartTimestamp = startTimestamp; - long intervalEndTimestamp = startTimestamp + interval; - - // Eigentliche Verarbeitung - - while (getMinOfArray(currentTsSolar) <= endTimestamp || getMinOfArray(currentTsMeter) <= endTimestamp) { - System.out.print(intervalStartTimestamp + ": "); - - for (int iSolar = 0; iSolar < channelIdsSolar.length; iSolar++) { - currentTsSolar[iSolar] = intervalStartTimestamp; - - while (currentTsSolar[iSolar] < intervalEndTimestamp && (noNextRecordSolar[iSolar] || rsSolar[iSolar].next())) { - if (noNextRecordSolar[iSolar]) { - noNextRecordSolar[iSolar] = false; - } - - final long tsSolar = rsSolar[iSolar].getLong("timestamp"); - final double value = rsSolar[iSolar].getDouble("value") > 1.0 ? rsSolar[iSolar].getDouble("value") : 0.0; - final long tsDiff = (tsSolar < intervalEndTimestamp) ? tsSolar - currentTsSolar[iSolar] : intervalEndTimestamp - currentTsSolar[iSolar]; - - currentTsSolar[iSolar] = tsSolar; - - intervalProduced += Math.round(value * tsDiff); - - if (currentTsSolar[iSolar] >= intervalEndTimestamp) { - noNextRecordSolar[iSolar] = true; - } - System.out.print("."); - } - } - - double meterValue = 0; - for (int iMeter = 0; iMeter < channelIdsMeter.length; iMeter++) { - currentTsMeter[iMeter] = intervalStartTimestamp; - - while (currentTsMeter[iMeter] < intervalEndTimestamp && (noNextRecordMeter[iMeter] || rsMeter[iMeter].next())) { - if (noNextRecordMeter[iMeter]) { - noNextRecordMeter[iMeter] = false; - } - final long tsMeter = rsMeter[iMeter].getLong("timestamp"); - final double value = rsMeter[iMeter].getDouble("value"); - final long tsDiff = (tsMeter < intervalEndTimestamp) ? tsMeter - currentTsMeter[iMeter] : intervalEndTimestamp - currentTsMeter[iMeter]; - - currentTsMeter[iMeter] = tsMeter; - - meterValue += Math.round(value * tsDiff); - - if (currentTsMeter[iMeter] >= intervalEndTimestamp) { - noNextRecordMeter[iMeter] = true; - } - System.out.print("#"); - } - } - if (meterValue > 0.0) { - intervalObtained += Math.round(meterValue); - } else { - intervalInjected += Math.abs(Math.round(meterValue)); - } - - System.out.println(" " + intervalProduced + " / " + intervalObtained + " / " + intervalInjected); - - result.add(new Aggregate2(houseId, intervalStartTimestamp, intervalEndTimestamp, intervalProduced, intervalObtained, intervalInjected)); - - intervalStartTimestamp += interval; - intervalEndTimestamp += interval; - - intervalInjected = 0; - intervalObtained = 0; - intervalProduced = 0; - } - - // Aufräumen - for (int i = 0; i < channelIdsSolar.length; i++) { - rsSolar[i].close(); - stmtSolar[i].close(); - } - - for (int i = 0; i < channelIdsMeter.length; i++) { - rsMeter[i].close(); - stmtMeter[i].close(); - } - - return result; - } - - private static long getMinOfArray(final long[] input) { - long result = Long.MAX_VALUE; - for (long i : input) { - if (i < result) { - result = i; - } - } - return result; - } - private static void saveValues(final Connection con, final List aggregates, final int houseId) throws SQLException { System.out.println("Saving entries... : " + aggregates.size()); try (final PreparedStatement stmt = con.prepareStatement("INSERT INTO tobias_aggregate2 (house_id, timestamp_start, timestamp_end, produced_energy, obtained_energy, injected_energy) VALUES (?, ?, ?, ?, ?, ?)")) { diff --git a/src/main/java/info/peper/vz/rest/VzRestController.java b/src/main/java/info/peper/vz/rest/VzRestController.java index 5b72f0e..68cd1df 100644 --- a/src/main/java/info/peper/vz/rest/VzRestController.java +++ b/src/main/java/info/peper/vz/rest/VzRestController.java @@ -12,9 +12,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -86,7 +83,7 @@ class VzRestController { @RequestParam("timestampEnd")final long timestampEnd, @RequestParam("houseId")final int houseId) { final List aggregates = jdbcTemplate.query( - "SELECT MIN(timestamp_start) AS min_ts_start, MAX(timestamp_end) AS max_ts_end, SUM(produced_energy) AS sum_produced, SUM(obtained_energy) AS sum_obtained, SUM(injected_energy) AS sum_injected FROM volkszaehler.tobias_aggregate2 WHERE house_id=? AND timestamp_start>=? AND timestamp_end<=?;", + "SELECT MIN(timestamp_start) AS min_ts_start, MAX(timestamp_end) AS max_ts_end, SUM(produced_energy)/3600 AS sum_produced, SUM(obtained_energy)/3600 AS sum_obtained, SUM(injected_energy)/3600 AS sum_injected FROM volkszaehler.tobias_aggregate2 WHERE house_id=? AND timestamp_start>=? AND timestamp_end<=?;", (rs, rowNum) -> new Aggregate2(houseId, rs.getLong("min_ts_start"), rs.getLong("max_ts_end"), rs.getLong("sum_produced"), rs.getLong("sum_obtained"), rs.getLong("sum_injected")), houseId ,timestampStart, timestampEnd); @@ -95,30 +92,16 @@ class VzRestController { } final Aggregate2 aggregate = aggregates.iterator().next(); - double sumPos = aggregate.getSumPositive(); - double sumNeg = aggregate.getSumNegative(); - log.debug("sumPos: " + sumPos + " / sumNeg: " + sumNeg); + log.debug("energyProduced: " + aggregate.getProducedEnergy() + " / energyObtained: " + aggregate.getObtainedEnergy() + " / injectedEnergy: " + aggregate.getInjectedEnergy()); log.debug("timestampStart: " + timestampStart); log.debug("timestampEnd: " + timestampEnd); log.debug("firstTimestamp: " + aggregate.getTimestampStart()); log.debug("lastTimestamp: " + aggregate.getTimestampEnd()); - if (timestampStart < aggregate.getTimestampStart() ) { - final Sums startSums = getSums(timestampStart, aggregate.getTimestampStart(), channelId); - sumPos += startSums.getSumPositive(); - sumNeg += startSums.getSumNegative(); - log.debug("Start: " + startSums.toString()); - } - if (timestampEnd > aggregate.getTimestampEnd()) { - final Sums endSums = getSums(aggregate.getTimestampEnd(), timestampEnd, channelId); - sumPos += endSums.getSumPositive(); - sumNeg += endSums.getSumNegative(); - log.debug("End: " + endSums.toString()); - - } - sumPos /= 3600; - sumNeg /= 3600; - return new Sums(Math.round(sumPos), Math.round(sumNeg)); + return new Sums2( + Math.round(aggregate.getInjectedEnergy()), + Math.round(aggregate.getObtainedEnergy()), + Math.round(aggregate.getProducedEnergy())); } @GetMapping("/data/sumsWithFactor") @@ -230,15 +213,38 @@ class VzRestController { return sb.toString(); } - - @GetMapping("/test/{name}") - String hello(@PathVariable("name")final String name) { - return "Hello " + name + "!"; - } - - @PostMapping("/test") - Aggregate newAggregate(@RequestBody final Aggregate aggregate) { - return aggregateRep.save(aggregate); + @GetMapping("/data/summary2") + String getSummary2(@RequestParam("timestampStart")final long timestampStart, + @RequestParam("timestampEnd")final long timestampEnd, + @RequestParam("contractId")final int contractId) { + final NumberFormat formatCurrency = new DecimalFormat("#,##0.00", new DecimalFormatSymbols(Locale.GERMAN)); + final NumberFormat formatPercent = new DecimalFormat("#,##0.00", new DecimalFormatSymbols(Locale.GERMAN)); + final NumberFormat formatEnergy = new DecimalFormat("#,##0", new DecimalFormatSymbols(Locale.GERMAN)); + final List prices = this.getPrices(timestampStart, timestampEnd, contractId); + + + float savedMoney = 0; + long totalProduced = 0; + long totalObtained = 0; + long totalInjected = 0; + for (EnergyPrice price : prices) { + final long tsStart = Math.max(price.getTimestampStart(), timestampStart); + final long tsEnd = Math.min(price.getTimestampEnd(), timestampEnd); + final Sums2 sums = getData2(tsStart, tsEnd, contractId); + savedMoney += (float)(sums.getProduced() - sums.getInjected())/1000000 * price.getPrice(); + totalProduced += sums.getProduced(); + totalObtained += sums.getObtained(); + totalInjected += sums.getInjected(); + } + final StringBuilder sb = new StringBuilder(); + sb.append("Erzeugter Strom von der Photovoltaik: " + formatEnergy.format(totalProduced/1000000) + " kWh\n"); + sb.append("Eingespeister Strom von der Photovoltaik: " + formatEnergy.format(totalInjected/1000000) + " kWh\n"); + sb.append("Genutzter Strom von der Photovoltaik: " + formatEnergy.format((totalProduced-totalInjected)/1000000) + " kWh (="); + sb.append(formatPercent.format((float)(totalProduced-totalInjected)/(float)totalProduced*100) + " %)\n"); + sb.append("Bezogener Strom: " + formatEnergy.format(totalObtained/1000000) + " kWh\n"); + sb.append("Autakie: " + formatPercent.format((float)(totalProduced-totalInjected)/(float)(totalObtained+totalProduced-totalInjected)*100) + " %\n"); + sb.append("Eingespartes Geld: " + formatCurrency.format(savedMoney) + "€\n"); + return sb.toString(); } private Sums getSums(final long startTimestamp, diff --git a/src/main/java/info/peper/vz/rest/bo/db/House.java b/src/main/java/info/peper/vz/rest/bo/db/House.java new file mode 100644 index 0000000..6bfdd10 --- /dev/null +++ b/src/main/java/info/peper/vz/rest/bo/db/House.java @@ -0,0 +1,81 @@ +package info.peper.vz.rest.bo.db; + +import java.io.Serializable; +import java.util.Objects; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; + +@Entity(name = "tobias_house") +@IdClass(House.CompositeKey.class) +public class House { + public static class CompositeKey implements Serializable { + private static final long serialVersionUID = 3097284483123288289L; + private int houseId; + private int type; + private int channelId; + @Override + public int hashCode() { + return Objects.hash(channelId, houseId, type); + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CompositeKey other = (CompositeKey) obj; + return channelId == other.channelId && houseId == other.houseId && type == other.type; + } + } + + House() { + super(); + } + + public House(int houseId, int type, int channelId) { + super(); + this.houseId = houseId; + this.type = type; + this.channelId = channelId; + } + @Id + @Column(name="house_id") + private int houseId; + @Id + @Column(name="type") + private int type; + @Id + @Column(name="channel_id") + private int channelId; + + public int getHouseId() { + return houseId; + } + + public void setHouseId(int houseId) { + this.houseId = houseId; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getChannelId() { + return channelId; + } + + public void setChannelId(int channelId) { + this.channelId = channelId; + } + + +}