true
if there are any results.
52 | */
53 | public static boolean hasResult(PreparedStatement ps) throws SQLException {
54 | try (ResultSet rs = ps.executeQuery()) {
55 | return rs.next();
56 | }
57 | }
58 |
59 | /**
60 | * Convert {@link Date} to {@link Timestamp}.
61 | * If date
is null
, it returns null
.
62 | */
63 | public static Timestamp toTimestamp(Date date) {
64 | if (date == null) {
65 | return null;
66 | }
67 | return new Timestamp(date.getTime());
68 | }
69 |
70 | public void createIndexIfNotExists(
71 | String table, String column) throws SQLException {
72 | try (PreparedStatement ps = conn.prepareStatement(
73 | String.format("CREATE INDEX IF NOT EXISTS %s_%s_idx ON %s(%s);",
74 | table, column, table, column))) {
75 | ps.executeUpdate();
76 | }
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/fiets/db/FeedDao.java:
--------------------------------------------------------------------------------
1 | package fiets.db;
2 |
3 | import java.sql.Connection;
4 | import java.sql.PreparedStatement;
5 | import java.sql.ResultSet;
6 | import java.sql.SQLException;
7 | import java.sql.Statement;
8 | import java.util.ArrayList;
9 | import java.util.Date;
10 | import java.util.List;
11 | import java.util.Optional;
12 |
13 | import org.apache.logging.log4j.LogManager;
14 | import org.apache.logging.log4j.Logger;
15 |
16 | import fiets.model.Feed;
17 | import fiets.model.FeedInfo;
18 |
19 | /**
20 | * DAO for the feeds table.
21 | */
22 | public class FeedDao {
23 |
24 | private static final Logger log = LogManager.getLogger();
25 | private Database db;
26 |
27 | public FeedDao(Database theDb) throws SQLException {
28 | db = theDb;
29 | createTable();
30 | createIndexes();
31 | }
32 |
33 | private int createTable() throws SQLException {
34 | try (PreparedStatement ps = db.getConnection().prepareStatement(
35 | "CREATE TABLE IF NOT EXISTS feed ("
36 | + "id BIGINT PRIMARY KEY AUTO_INCREMENT,"
37 | + "lastAccess DATETIME,"
38 | + "lastStatus VARCHAR(1024),"
39 | + "location VARCHAR(2048),"
40 | + "title VARCHAR(1024)"
41 | + ");")) {
42 | return ps.executeUpdate();
43 | }
44 | }
45 |
46 | private void createIndex(String column) throws SQLException {
47 | db.createIndexIfNotExists("feed", column);
48 | }
49 |
50 | private void createIndexes() throws SQLException {
51 | createIndex("id");
52 | createIndex("location");
53 | }
54 |
55 | public Feed saveFeed(Feed feed) throws SQLException {
56 | if (feed.getId() == 0) {
57 | if (existsFeed(feed.getLocation())) {
58 | updateFeedByLocation(feed);
59 | } else {
60 | return insertFeed(feed);
61 | }
62 | } else {
63 | updateFeedById(feed);
64 | }
65 | return feed;
66 | }
67 |
68 | public void touchFeed(Feed feed, String status) throws SQLException {
69 | Connection conn = db.getConnection();
70 | try (PreparedStatement ps = conn.prepareStatement(
71 | "UPDATE feed SET lastAccess=?,lastStatus=? WHERE id=?")) {
72 | int i = 0;
73 | ps.setTimestamp(++i, Database.toTimestamp(new Date()));
74 | ps.setString(++i, status);
75 | ps.setLong(++i, feed.getId());
76 | ps.executeUpdate();
77 | }
78 | }
79 |
80 | public long lastFeedUpdate() throws SQLException {
81 | Connection conn = db.getConnection();
82 | try (PreparedStatement ps = conn.prepareStatement(
83 | "SELECT MAX(lastAccess) FROM feed")) {
84 | try (ResultSet rs = ps.executeQuery()) {
85 | if (rs.next()) {
86 | return rs.getTimestamp(1).getTime();
87 | } else {
88 | return 0l;
89 | }
90 | }
91 | }
92 | }
93 |
94 | private void updateFeedById(Feed feed) throws SQLException {
95 | Connection conn = db.getConnection();
96 | try (PreparedStatement ps = conn.prepareStatement(
97 | "UPDATE feed SET location=?,title=?,lastAccess=?"
98 | + "WHERE id=?")) {
99 | ps.setString(1, feed.getLocation());
100 | ps.setString(2, feed.getTitle());
101 | ps.setTimestamp(3, Database.toTimestamp(feed.getLastAccess()));
102 | ps.setLong(4, feed.getId());
103 | ps.executeUpdate();
104 | }
105 | log.debug("Updated feed {} with ID {}.", feed.getLocation(), feed.getId());
106 | }
107 |
108 | private void updateFeedByLocation(Feed feed) throws SQLException {
109 | Connection conn = db.getConnection();
110 | try (PreparedStatement ps = conn.prepareStatement(
111 | "UPDATE feed SET lastAccess=? WHERE location=?")) {
112 | ps.setTimestamp(1, Database.toTimestamp(feed.getLastAccess()));
113 | ps.setString(2, feed.getLocation());
114 | ps.executeUpdate();
115 | }
116 | log.debug("Updated feed {} with ID {}.", feed.getLocation(), feed.getId());
117 | }
118 |
119 | private boolean existsFeed(String location) throws SQLException {
120 | try (PreparedStatement ps = db.getConnection().prepareStatement(
121 | "SELECT * FROM feed WHERE location=?")) {
122 | ps.setString(1, location);
123 | return Database.hasResult(ps);
124 | }
125 | }
126 |
127 | private Feed insertFeed(Feed feed) throws SQLException {
128 | try (PreparedStatement ps = db.getConnection().prepareStatement(
129 | "INSERT INTO feed (location, title, lastAccess, lastStatus) "
130 | + "VALUES (?,?,?,?)",
131 | Statement.RETURN_GENERATED_KEYS)) {
132 | ps.setString(1, feed.getLocation());
133 | ps.setString(2, feed.getTitle());
134 | ps.setTimestamp(3, Database.toTimestamp(feed.getLastAccess()));
135 | ps.setString(4, feed.getLastStatus());
136 | ps.executeUpdate();
137 | feed = new Feed(Database.getGeneratedKey(ps),
138 | feed.getLocation(), feed.getTitle(), feed.getLastAccess(),
139 | feed.getLastStatus());
140 | }
141 | log.debug("Inserted feed {} with ID {}", feed.getLocation(), feed.getId());
142 | return feed;
143 | }
144 |
145 | public Optional