comparison backend/src/main/java/org/dive4elements/river/importer/ImportCrossSectionLine.java @ 8986:392bbcd8a88b

Database inserts accelerated by suppressing unnecessary database queries for new data series
author mschaefer
date Sun, 08 Apr 2018 18:07:06 +0200
parents 36455dfcb788
children
comparison
equal deleted inserted replaced
8985:27851cfda84a 8986:392bbcd8a88b
6 * documentation coming with Dive4Elements River for details. 6 * documentation coming with Dive4Elements River for details.
7 */ 7 */
8 8
9 package org.dive4elements.river.importer; 9 package org.dive4elements.river.importer;
10 10
11 import org.dive4elements.river.model.CrossSection; 11 import java.util.Comparator;
12 import org.dive4elements.river.model.CrossSectionPoint;
13 import org.dive4elements.river.model.CrossSectionLine;
14
15 import org.hibernate.Session;
16 import org.hibernate.Query;
17
18 import java.util.List; 12 import java.util.List;
19 import java.util.Comparator;
20 import java.util.Map; 13 import java.util.Map;
21 import java.util.TreeMap; 14 import java.util.TreeMap;
15
16 import org.dive4elements.river.importer.common.StoreMode;
17 import org.dive4elements.river.model.CrossSection;
18 import org.dive4elements.river.model.CrossSectionLine;
19 import org.dive4elements.river.model.CrossSectionPoint;
20 import org.hibernate.Query;
21 import org.hibernate.Session;
22 22
23 /** 23 /**
24 * A CrossSectionLine (containing points) ready to be transformed into a mapped 24 * A CrossSectionLine (containing points) ready to be transformed into a mapped
25 * object and written to db (used in importer). 25 * object and written to db (used in importer).
26 */ 26 */
27 public class ImportCrossSectionLine 27 public class ImportCrossSectionLine
28 { 28 {
29 public static final Comparator<CrossSectionPoint> INDEX_CMP = 29 public static final Comparator<CrossSectionPoint> INDEX_CMP =
30 new Comparator<CrossSectionPoint>() { 30 new Comparator<CrossSectionPoint>() {
31 public int compare(CrossSectionPoint a, CrossSectionPoint b) { 31 @Override
32 return a.getColPos().compareTo(b.getColPos()); 32 public int compare(final CrossSectionPoint a, final CrossSectionPoint b) {
33 } 33 return a.getColPos().compareTo(b.getColPos());
34 }; 34 }
35 };
35 36
36 protected Double km; 37 protected Double km;
37 protected ImportCrossSection crossSection; 38 protected ImportCrossSection crossSection;
38 protected List<XY> points; 39 protected List<XY> points;
40 protected StoreMode storeMode;
39 41
40 protected CrossSectionLine peer; 42 protected CrossSectionLine peer;
41 43
42 public ImportCrossSectionLine() { 44 public ImportCrossSectionLine() {
43 } 45 }
44 46
45 public ImportCrossSectionLine(Double km, List<XY> points) { 47 public ImportCrossSectionLine(final Double km, final List<XY> points) {
46 this.km = km; 48 this.km = km;
47 this.points = points; 49 this.points = points;
50 this.storeMode = StoreMode.NONE;
48 } 51 }
49 52
50 public ImportCrossSection getCrossSection() { 53 public ImportCrossSection getCrossSection() {
51 return crossSection; 54 return this.crossSection;
52 } 55 }
53 56
54 public void setCrossSection(ImportCrossSection crossSection) { 57 public void setCrossSection(final ImportCrossSection crossSection) {
55 this.crossSection = crossSection; 58 this.crossSection = crossSection;
56 } 59 }
57 60
58 public Double getKm() { 61 public Double getKm() {
59 return km; 62 return this.km;
60 } 63 }
61 64
62 public void setKm(Double km) { 65 public void setKm(final Double km) {
63 this.km = km; 66 this.km = km;
64 } 67 }
65 68
66 public void storeDependencies() { 69 public void storeDependencies() {
67 storePoints(); 70 storePoints();
68 } 71 }
69 72
70 73
71 /** Write a line and its points. */ 74 /** Write a line and its points. */
72 protected void storePoints() { 75 protected void storePoints() {
73 CrossSectionLine csl = getPeer(); 76 final CrossSectionLine csl = getPeer();
74 77 if (this.storeMode == StoreMode.INSERT) {
75 Map<CrossSectionPoint, CrossSectionPoint> map = 78 insertPoints();
76 new TreeMap<CrossSectionPoint, CrossSectionPoint>(INDEX_CMP); 79 return;
80 }
81 final Map<CrossSectionPoint, CrossSectionPoint> map =
82 new TreeMap<>(INDEX_CMP);
77 83
78 // Build index for faster (index) collision lookup. 84 // Build index for faster (index) collision lookup.
79 List<CrossSectionPoint> ps = csl.getPoints(); 85 final List<CrossSectionPoint> ps = csl.getPoints();
80 if (ps != null) { 86 if (ps != null) {
81 for (CrossSectionPoint point: ps) { 87 for (final CrossSectionPoint point: ps) {
82 map.put(point, point); 88 map.put(point, point);
83 } 89 }
84 } 90 }
85 91
86 Session session = 92 final Session session = ImporterSession.getInstance().getDatabaseSession();
87 ImporterSession.getInstance().getDatabaseSession();
88 93
89 CrossSectionPoint key = new CrossSectionPoint(); 94 final CrossSectionPoint key = new CrossSectionPoint();
90 95
91 // Somehow it looks as if even with the map it is still possible that 96 // Somehow it looks as if even with the map it is still possible that
92 // multiple points with same id enter hibernate (and then violate a 97 // multiple points with same id enter hibernate (and then violate a
93 // constraint). -> TODO 98 // constraint). -> TODO
94 for (XY xy: points) { 99 for (final XY xy: this.points) {
95 key.setColPos(xy.getIndex()); 100 key.setColPos(xy.getIndex());
96 CrossSectionPoint csp = map.get(key); 101 CrossSectionPoint csp = map.get(key);
97 if (csp == null) { // create new 102 if (csp == null) { // create new
98 csp = new CrossSectionPoint( 103 csp = new CrossSectionPoint(
99 csl, key.getColPos(), 104 csl, key.getColPos(),
100 Double.valueOf(xy.getX()), 105 Double.valueOf(xy.getX()),
101 Double.valueOf(xy.getY())); 106 Double.valueOf(xy.getY()));
102 } 107 }
103 else { // update old 108 else { // update old
104 csp.setX(Double.valueOf(xy.getX())); 109 csp.setX(Double.valueOf(xy.getX()));
105 csp.setY(Double.valueOf(xy.getY())); 110 csp.setY(Double.valueOf(xy.getY()));
106 } 111 }
107 session.save(csp); 112 session.save(csp);
108 } 113 }
109 } 114 }
110 115
116 /**
117 * Insert the points of a new line into the database without previously querying the database
118 */
119 private void insertPoints() {
120 final Session session = ImporterSession.getInstance().getDatabaseSession();
121 for (final XY xy : this.points) {
122 session.save(new CrossSectionPoint(getPeer(), xy.getIndex(), xy.getX(), xy.getY()));
123 }
124 }
125
111 /** Pull database-mapped object from db, or create (and save) one. */ 126 /** Pull database-mapped object from db, or create (and save) one. */
112 public CrossSectionLine getPeer() { 127 public CrossSectionLine getPeer() {
113 if (peer == null) { 128 if (this.peer == null) {
114 CrossSection cs = crossSection.getPeer(); 129 final CrossSection cs = this.crossSection.getPeer();
115 130 final Session session = ImporterSession.getInstance().getDatabaseSession();
116 Session session = 131 List<CrossSectionLine> lines;
117 ImporterSession.getInstance().getDatabaseSession(); 132 if (this.crossSection.storeMode == StoreMode.INSERT)
118 133 lines = null;
119 Query query = session.createQuery( 134 else {
120 "from CrossSectionLine where crossSection=:cs and km=:km"); 135 final Query query = session.createQuery("from CrossSectionLine where crossSection=:cs and km=:km");
121 query.setParameter("cs", cs); 136 query.setParameter("cs", cs);
122 query.setParameter("km", km); 137 query.setParameter("km", this.km);
123 138 lines = query.list();
124 List<CrossSectionLine> lines = query.list(); 139 }
125 if (lines.isEmpty()) { 140 if ((lines == null) || lines.isEmpty()) {
126 peer = new CrossSectionLine(cs, km); 141 this.peer = new CrossSectionLine(cs, this.km);
127 session.save(peer); 142 session.save(this.peer);
143 this.storeMode = StoreMode.INSERT;
128 } 144 }
129 else { 145 else {
130 peer = lines.get(0); 146 this.peer = lines.get(0);
147 this.storeMode = StoreMode.UPDATE;
131 } 148 }
132 } 149 }
133 return peer; 150 return this.peer;
134 } 151 }
135 } 152 }
136 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : 153 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org