From cd6e810144e1cfed1e88f974a30b40090d4f6159 Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Sun, 26 Oct 2014 19:07:37 +1100 Subject: [PATCH] Refactor hibernate orm usage - VictimsHibernate is now used as a utility class - VictimsDatabase now contains database interaction specifics - [Issue #45] LastUpdate is now in-database - Move to in database cache - Update VictimsResultCacheTest to test in database caching - Updated models - Misc. code refactor --- .../redhat/victims/database/VictimsDB.java | 24 +- .../victims/database/VictimsDatabase.java | 280 ++++++++++++++++++ .../victims/database/VictimsHibernate.java | 237 +-------------- .../redhat/victims/database/model/CVE.java | 13 +- .../victims/database/model/FileHash.java | 10 +- .../victims/database/model/Metadata.java | 77 +++-- .../redhat/victims/database/model/Record.java | 23 +- .../redhat/victims/database/model/Status.java | 6 +- 8 files changed, 395 insertions(+), 275 deletions(-) create mode 100644 src/main/java/com/redhat/victims/database/VictimsDatabase.java diff --git a/src/main/java/com/redhat/victims/database/VictimsDB.java b/src/main/java/com/redhat/victims/database/VictimsDB.java index 4e31baf..5813618 100644 --- a/src/main/java/com/redhat/victims/database/VictimsDB.java +++ b/src/main/java/com/redhat/victims/database/VictimsDB.java @@ -31,14 +31,14 @@ /** * A class providing easy instantiation of DB implementation based on the * configured driver. - * + * * @author abn - * + * */ public class VictimsDB { /** * The default driver class to use. - * + * * @return */ public static String defaultDriver() { @@ -47,7 +47,7 @@ public static String defaultDriver() { /** * Get the default url for a preconfigured driver. - * + * * @return */ public static String defaultURL(String driver) { @@ -63,7 +63,7 @@ public static String defaultURL(String driver) { /** * The default url for the default driver. - * + * * @return */ public static String defaultURL() { @@ -73,7 +73,7 @@ public static String defaultURL() { /** * Fetches an instance implementing {@link VictimsDBInterface} using the * configured driver. - * + * * @return A {@link VictimsDBInterface} implementation. * @throws VictimsException */ @@ -88,14 +88,14 @@ public static VictimsDBInterface db() throws VictimsException { + VictimsConfig.Key.DB_URL); } } - return (VictimsDBInterface) new VictimsHibernate(); + return (VictimsDBInterface) new VictimsDatabase(); } /** * This class facilitates use of multiple driver classes - * + * * @author abn - * + * */ public static class Driver { public static final String H2 = "org.h2.Driver"; @@ -108,7 +108,7 @@ public static class Driver { /** * Test if a given driver class is configured. - * + * * @param driver * The driver class. * @return @@ -119,7 +119,7 @@ public static boolean exists(String driver) { /** * Get the default connection URL for a given driver. - * + * * @param driver * The driver class. * @param path @@ -132,7 +132,7 @@ public static String url(String driver, String path) { /** * Add a driver to use. - * + * * @param driver * The driver class. * @param urlFormat diff --git a/src/main/java/com/redhat/victims/database/VictimsDatabase.java b/src/main/java/com/redhat/victims/database/VictimsDatabase.java new file mode 100644 index 0000000..ed39afa --- /dev/null +++ b/src/main/java/com/redhat/victims/database/VictimsDatabase.java @@ -0,0 +1,280 @@ +package com.redhat.victims.database; + +import com.redhat.victims.VictimsConfig; +import com.redhat.victims.VictimsException; +import com.redhat.victims.VictimsRecord; +import com.redhat.victims.VictimsService; +import com.redhat.victims.database.model.CVE; +import com.redhat.victims.database.model.FileHash; +import com.redhat.victims.database.model.Metadata; +import com.redhat.victims.database.model.Record; +import com.redhat.victims.database.model.Status; +import com.redhat.victims.fingerprint.Algorithms; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.hibernate.Criteria; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +/** + * Created by abn on 10/26/14. + */ +public class VictimsDatabase implements VictimsDBInterface { + + @Override + public Date lastUpdated() throws VictimsException { + Throwable throwable = null; + try { + SimpleDateFormat sdf = new SimpleDateFormat( + VictimsRecord.DATE_FORMAT); + Date since; + + // The default start + since = sdf.parse("1970-01-01T00:00:00"); + + if (VictimsConfig.forcedUpdate()) { + return since; + } + + Session session = VictimsHibernate.openSession(); + Status lastUpdated = (Status) session.get(Status.class, StatusKey.LAST_UPDATED.toString()); + if (lastUpdated == null) { + since = sdf.parse(lastUpdated.getValue()); + } + return since; + } catch (ParseException e) { + throwable = e; + } + throw new VictimsException("Failed to retreive last updated data", + throwable); + } + + private void setLastUpdate(Date date) { + Session session = VictimsHibernate.openSession(); + try { + SimpleDateFormat sdf = new SimpleDateFormat(VictimsRecord.DATE_FORMAT); + session.save(new Status(StatusKey.LAST_UPDATED.toString(), sdf.format(date))); + } finally { + session.close(); + } + } + + protected void removeHashes(HashSet hashes) { + Session session = VictimsHibernate.openSession(); + String hql = "DELETE FROM Record r WHERE r.hash in :hashes"; + try { + session.createQuery(hql).setParameterList("hashes", hashes).executeUpdate(); + } finally { + session.close(); + } + } + + protected int remove(VictimsService.RecordStream recordStream) throws IOException { + HashSet hashes = new HashSet(); + while (recordStream.hasNext()) { + hashes.add(recordStream.getNext().hash); + } + removeHashes(hashes); + return hashes.size(); + } + + protected int update(VictimsService.RecordStream recordStream) throws IOException { + int count = 0; + Session session = VictimsHibernate.openSession(); + try { + Record record; + while (recordStream.hasNext()) { + VictimsRecord vr = recordStream.getNext(); + String hash = vr.hash.trim(); + Set filehashes = vr.getHashes(Algorithms.SHA512).keySet(); + + record = new Record(hash, filehashes.size()); + session.delete(record); + session.save(record); + + Transaction transaction = session.beginTransaction(); + Integer tcount = 0; + + // insert filehashes + for (String filehash : filehashes) { + VictimsHibernate.saveBatch(session, tcount++, new FileHash(record, filehash)); + } + // insert metadata key-value pairs + HashMap md = vr.getFlattenedMetaData(); + for (String key : md.keySet()) { + VictimsHibernate.saveBatch(session, tcount++, new Metadata(record, key.trim(), md.get(key).trim())); + } + + // insert cves + for (String cve : vr.cves) { + VictimsHibernate.saveBatch(session, tcount++, new CVE(record, cve.trim())); + } + + transaction.commit(); + + count++; + } + } finally { + session.close(); + } + return count; + } + + @Override + public void synchronize() throws VictimsException { + + Throwable throwable = null; + try { + VictimsService service = new VictimsService(); + Date since = lastUpdated(); + + int removed = remove(service.removed(since)); + int updated = update(service.updates(since)); + + if (removed > 0 || updated > 0) { + VictimsResultCache.purge(); + } + + setLastUpdate(new Date()); + } catch (IOException e) { + throwable = e; + } + + if (throwable != null) { + throw new VictimsException("Failed to sync database", throwable); + } + } + + /** + * Internal method implementing search for vulnerabilities checking if the + * given {@link VictimsRecord}'s contents are a superset of a record in the + * victims database. + * + * @param vr + * @return + */ + protected HashSet getEmbeddedVulnerabilities(VictimsRecord vr) { + HashSet cves = new HashSet(); + + Set fileHashes = vr.getHashes(Algorithms.SHA512).keySet(); + if (fileHashes.size() <= 0) { + return cves; + } + + Session session = VictimsHibernate.openSession(); + try { + Criteria matchCriteria = session.createCriteria(FileHash.class) + .add(Restrictions.in("filehash", fileHashes)) + .setProjection(Projections.projectionList() + .add(Projections.groupProperty("record")) + .add(Projections.count("filehash"))); + for (Object object : matchCriteria.list()) { + Object[] tuple = (Object[]) object; + Record record = (Record) tuple[0]; + Long count = (Long) tuple[1]; + if (count.equals(new Long(record.getFileCount()))) { + for (CVE c : record.getCves()) { + cves.add(c.getCve()); + } + } + } + } finally { + session.close(); + } + return cves; + } + + public HashSet getVulnerabilities(VictimsRecord vr) + throws VictimsException { + try { + + HashSet cached = VictimsResultCache.get(vr.hash); + if (cached != null) { + return cached; + } + + HashSet cves = new HashSet(); + + // Match jar sha512 + cves.addAll(getVulnerabilities(vr.hash.trim())); + + // Match any embedded filehashes + cves.addAll(getEmbeddedVulnerabilities(vr)); + + VictimsResultCache.put(vr.hash, cves); + return cves; + } catch (Throwable e) { + throw new VictimsException( + "Could not determine vulnerabilities for hash: " + vr.hash, + e); + } + } + + @Override + public HashSet getVulnerabilities(String sha512) throws VictimsException { + Session session = VictimsHibernate.openSession(); + try { + HashSet cves = new HashSet(); + for (Record record : (List) session.createCriteria(Record.class) + .add(Restrictions.eq("hash", sha512)).list()) { + cves.addAll(record.getCveNames()); + } + return cves; + } finally { + session.close(); + } + } + + @Override + public HashSet getVulnerabilities(HashMap props) throws VictimsException { + Session session = VictimsHibernate.openSession(); + try { + HashSet cves = new HashSet(); + + List properties = new ArrayList(); + for (String key : props.keySet()) { + properties.add(new Metadata.MetadataProperty(key, props.get(key))); + } + + String hql = "SELECT m.record, count(*) FROM Metadata m WHERE m.property IN :propset GROUP BY m.record"; + Query propMatch = session.createQuery(hql); + propMatch.setParameterList("propset", properties); + + for (Object obj : propMatch.list()) { + Object[] tuple = (Object[]) obj; + Record record = (Record) tuple[0]; + Long count = (Long) tuple[1]; + if (count.equals(new Long(props.size()))) { + for (CVE c : record.getCves()) { + cves.add(c.getCve()); + } + } + } + return cves; + } finally { + session.close(); + } + } + + @Override + public int getRecordCount() throws VictimsException { + Session session = VictimsHibernate.openSession(); + try { + return (Integer) session.createCriteria(Record.class).setProjection(Projections.rowCount()).list().get(0); + } finally { + session.close(); + } + } + +} diff --git a/src/main/java/com/redhat/victims/database/VictimsHibernate.java b/src/main/java/com/redhat/victims/database/VictimsHibernate.java index a4639b8..10a9950 100644 --- a/src/main/java/com/redhat/victims/database/VictimsHibernate.java +++ b/src/main/java/com/redhat/victims/database/VictimsHibernate.java @@ -1,39 +1,20 @@ package com.redhat.victims.database; import com.redhat.victims.VictimsConfig; -import com.redhat.victims.VictimsException; -import com.redhat.victims.VictimsRecord; -import com.redhat.victims.VictimsService; -import com.redhat.victims.database.model.CVE; -import com.redhat.victims.database.model.FileHash; -import com.redhat.victims.database.model.Metadata; -import com.redhat.victims.database.model.Record; -import com.redhat.victims.database.model.Status; -import com.redhat.victims.fingerprint.Algorithms; -import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.SessionFactory; -import org.hibernate.Transaction; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Restrictions; import org.hibernate.service.ServiceRegistry; import org.reflections.Reflections; -import java.io.IOException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; import java.util.Properties; import java.util.Set; /** * Created by abn on 10/25/14. */ -public class VictimsHibernate implements VictimsDBInterface { +public class VictimsHibernate { private static SessionFactory sessionFactory; private static ServiceRegistry serviceRegistry; private static Configuration configuration; @@ -48,7 +29,7 @@ protected static Properties getConfigurationProperties() { properties.setProperty("hibernate.hbm2ddl.auto", "update"); properties.setProperty("hibernate.jdbc.batch_size", "20"); - properties.setProperty("hibernate.format_sql", "false"); + properties.setProperty("hibernate.format_sql", "true"); properties.setProperty("hibernate.show_sql", "false"); properties.setProperty("hibernate.connection.pool_size", "2"); properties.setProperty("hibernate.current_session_context_class", "thread"); @@ -66,7 +47,7 @@ protected static Set> getMappedClasses() { configuration.configure(); configuration.setProperties(getConfigurationProperties()); - for(Class clazz : getMappedClasses()) { + for (Class clazz : getMappedClasses()) { configuration.addAnnotatedClass(clazz); } @@ -75,219 +56,15 @@ protected static Set> getMappedClasses() { sessionFactory = configuration.buildSessionFactory(serviceRegistry); } - @Override - public Date lastUpdated() throws VictimsException { - Throwable throwable = null; - try { - SimpleDateFormat sdf = new SimpleDateFormat( - VictimsRecord.DATE_FORMAT); - Date since; - - // The default start - since = sdf.parse("1970-01-01T00:00:00"); - - if (VictimsConfig.forcedUpdate()) { - return since; - } - - Session session = sessionFactory.openSession(); - Status lastUpdated = (Status) session.get(Status.class, StatusKey.LAST_UPDATED); - if (lastUpdated == null) { - since = sdf.parse(lastUpdated.getValue()); - } - return since; - } catch (ParseException e) { - throwable = e; - } - throw new VictimsException("Failed to retreive last updated data", - throwable); - } - - protected void removeHashes(HashSet hashes) { - Session session = sessionFactory.openSession(); - String hql = "DELETE FROM Record r WHERE r.hash in :hashes"; - try { - session.createQuery(hql).setParameterList("hashes", hashes).executeUpdate(); - } finally { - session.close(); - } - } - - protected int remove(VictimsService.RecordStream recordStream) throws IOException { - HashSet hashes = new HashSet(); - while(recordStream.hasNext()) { - hashes.add(recordStream.getNext().hash); - } - removeHashes(hashes); - return hashes.size(); + public static Session openSession() { + return sessionFactory.openSession(); } - private void saveBatch(Session session, Integer count, Object object) { + public static void saveBatch(Session session, Integer count, Object object) { session.save(object); - if ( count % Integer.parseInt(configuration.getProperty("hibernate.jdbc.batch_size")) == 0 ) { + if (count % Integer.parseInt(configuration.getProperty("hibernate.jdbc.batch_size")) == 0) { session.flush(); session.clear(); } } - - protected int update(VictimsService.RecordStream recordStream) throws IOException { - int count = 0; - Session session = sessionFactory.openSession(); - try { - Record record; - while (recordStream.hasNext()) { - VictimsRecord vr = recordStream.getNext(); - String hash = vr.hash.trim(); - Set filehashes = vr.getHashes(Algorithms.SHA512).keySet(); - - record = new Record(hash, filehashes.size()); - session.delete(record); - session.save(record); - - Transaction transaction = session.beginTransaction(); - Integer tcount = 0; - - // insert filehashes - for (String filehash : filehashes) { - saveBatch(session, tcount++, new FileHash(record, filehash)); - } - // insert metadata key-value pairs - HashMap md = vr.getFlattenedMetaData(); - for (String key : md.keySet()) { - saveBatch(session, tcount++, new Metadata(record, key.trim(), md.get(key).trim())); - } - - // insert cves - for (String cve : vr.cves) { - saveBatch(session, tcount++, new CVE(record, cve.trim())); - } - - transaction.commit(); - - count++; - } - } finally { - session.close(); - } - return count; - } - - @Override - public void synchronize() throws VictimsException { - - Throwable throwable = null; - try { - VictimsService service = new VictimsService(); - Date since = lastUpdated(); - - int removed = remove(service.removed(since)); - int updated = update(service.updates(since)); - - if (removed > 0 || updated > 0) { - //TODO: cache.purge(); - } - - //TODO: setLastUpdate(new Date()); - } catch (IOException e) { - throwable = e; - } - - if (throwable != null) { - throw new VictimsException("Failed to sync database", throwable); - } - } - - /** - * Internal method implementing search for vulnerabilities checking if the - * given {@link VictimsRecord}'s contents are a superset of a record in the - * victims database. - * - * @param vr - * @return - */ - protected HashSet getEmbeddedVulnerabilities(VictimsRecord vr) { - HashSet cves = new HashSet(); - - Set fileHashes = vr.getHashes(Algorithms.SHA512).keySet(); - if (fileHashes.size() <= 0) { - return cves; - } - - Session session = sessionFactory.openSession(); - try { - Criteria matchCriteria = session.createCriteria(FileHash.class) - .add(Restrictions.in("filehash", fileHashes)) - .setProjection(Projections.projectionList() - .add(Projections.groupProperty("record")) - .add(Projections.count("filehash"))); - for (Object object : matchCriteria.list()) { - Object[] tuple = (Object[]) object; - Record record = (Record) tuple[0]; - Long count = (Long) tuple[1]; - if (count.equals(new Long(record.getFileCount()))) { - for(CVE c : record.getCves()) { - cves.add(c.getCve()); - } - } - } - } finally { - session.close(); - } - return cves; - } - - public HashSet getVulnerabilities(VictimsRecord vr) - throws VictimsException { - try { - //TODO: cache - /*if (cache.exists(vr.hash)) { - return cache.get(vr.hash); - }*/ - HashSet cves = new HashSet(); - - // Match jar sha512 - cves.addAll(getVulnerabilities(vr.hash.trim())); - - // Match any embedded filehashes - cves.addAll(getEmbeddedVulnerabilities(vr)); - - //TODO: cache.add(vr.hash, cves); - return cves; - } catch (Throwable e) { - throw new VictimsException( - "Could not determine vulnerabilities for hash: " + vr.hash, - e); - } - } - - @Override - public HashSet getVulnerabilities(String sha512) throws VictimsException { - Session session = sessionFactory.openSession(); - try { - HashSet cves = new HashSet(); - for (Object obj : session.createCriteria(CVE.class) - .createAlias("record", "r") - .add(Restrictions.eq("r.hash", sha512)).list()) { - cves.add(((CVE) obj).getCve()); - } - return cves; - } finally { - session.close(); - } - } - - @Override - public HashSet getVulnerabilities(HashMap props) throws VictimsException { - return null; - } - - @Override - public int getRecordCount() throws VictimsException { - Session session = sessionFactory.openSession(); - try { - return (Integer) session.createCriteria(Record.class).setProjection(Projections.rowCount()).list().get(0); - } finally { - session.close(); - } - } } diff --git a/src/main/java/com/redhat/victims/database/model/CVE.java b/src/main/java/com/redhat/victims/database/model/CVE.java index aa28c5d..22e09a8 100644 --- a/src/main/java/com/redhat/victims/database/model/CVE.java +++ b/src/main/java/com/redhat/victims/database/model/CVE.java @@ -1,6 +1,14 @@ package com.redhat.victims.database.model; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.ForeignKey; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; /** * Created by abn on 10/25/14. @@ -21,7 +29,8 @@ public class CVE { @Column(name = "cve") private String cve; - public CVE() { } + public CVE() { + } public CVE(Record record, String cve) { this.record = record; diff --git a/src/main/java/com/redhat/victims/database/model/FileHash.java b/src/main/java/com/redhat/victims/database/model/FileHash.java index 14c93e0..4bea6b6 100644 --- a/src/main/java/com/redhat/victims/database/model/FileHash.java +++ b/src/main/java/com/redhat/victims/database/model/FileHash.java @@ -1,6 +1,14 @@ package com.redhat.victims.database.model; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.ForeignKey; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; /** * Created by abn on 10/25/14. diff --git a/src/main/java/com/redhat/victims/database/model/Metadata.java b/src/main/java/com/redhat/victims/database/model/Metadata.java index 395607f..fe3006f 100644 --- a/src/main/java/com/redhat/victims/database/model/Metadata.java +++ b/src/main/java/com/redhat/victims/database/model/Metadata.java @@ -1,6 +1,17 @@ package com.redhat.victims.database.model; -import javax.persistence.*; +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.ForeignKey; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; /** * Created by abn on 10/25/14. @@ -18,43 +29,65 @@ public class Metadata { @JoinColumn(foreignKey = @ForeignKey(name = "FK_RECORD")) private Record record; - @Column(name = "property") - private String property; - - @Column(name = "value") - private String value; + @Embedded + private MetadataProperty property; public Metadata() { } - public Metadata(Record record, String property, String value) { + public Metadata(Record record, String key, String value) { this.record = record; - this.property = property; - this.value = value; + this.property = new MetadataProperty(key, value); } - public String getProperty() { - return property; + public Record getRecord() { + return record; } - public void setProperty(String property) { - this.property = property; + public void setRecord(Record record) { + this.record = record; } - public String getValue() { - return value; + public MetadataProperty getProperty() { + return property; } - public void setValue(String value) { - this.value = value; + public void setProperty(MetadataProperty property) { + this.property = property; } - public Record getRecord() { - return record; - } + @Embeddable + public static class MetadataProperty implements Serializable { - public void setRecord(Record record) { - this.record = record; + @Column + private String key; + + @Column + private String value; + + public MetadataProperty() { + } + + public MetadataProperty(String value, String key) { + this.value = value; + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } } } diff --git a/src/main/java/com/redhat/victims/database/model/Record.java b/src/main/java/com/redhat/victims/database/model/Record.java index 3f170ef..01f6457 100644 --- a/src/main/java/com/redhat/victims/database/model/Record.java +++ b/src/main/java/com/redhat/victims/database/model/Record.java @@ -1,5 +1,7 @@ package com.redhat.victims.database.model; +import java.util.HashSet; +import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; @@ -11,7 +13,6 @@ import javax.persistence.Table; import javax.persistence.UniqueConstraint; import javax.validation.constraints.NotNull; -import java.util.Set; /** * Created by abn on 10/25/14. @@ -33,16 +34,16 @@ public class Record { @Column private Integer fileCount = 0; - @OneToMany(cascade=CascadeType.ALL) - @JoinColumn(name="record_id") + @OneToMany(cascade = CascadeType.ALL) + @JoinColumn(name = "record_id") private Set filehashes; - @OneToMany(cascade=CascadeType.ALL) - @JoinColumn(name="record_id") + @OneToMany(cascade = CascadeType.ALL) + @JoinColumn(name = "record_id") private Set cves; - @OneToMany(cascade=CascadeType.ALL) - @JoinColumn(name="record_id") + @OneToMany(cascade = CascadeType.ALL) + @JoinColumn(name = "record_id") private Set metadata; public Record() { @@ -89,4 +90,12 @@ public Set getCves() { public Set getMetadata() { return metadata; } + + public HashSet getCveNames() { + HashSet cves = new HashSet(); + for (CVE cve : getCves()) { + cves.add(cve.getCve()); + } + return cves; + } } \ No newline at end of file diff --git a/src/main/java/com/redhat/victims/database/model/Status.java b/src/main/java/com/redhat/victims/database/model/Status.java index 3e7a8b3..e9a4644 100644 --- a/src/main/java/com/redhat/victims/database/model/Status.java +++ b/src/main/java/com/redhat/victims/database/model/Status.java @@ -1,6 +1,10 @@ package com.redhat.victims.database.model; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; import javax.validation.constraints.NotNull; /**