如何将曲线存储到数据库
How to store curve to database
请问如何将曲线存储到数据库中。曲线对象由点数组表示。
我有两个选择:
1) 创建两个 tables,一个用于曲线,一个用于点
- 看起来像这样:
CURVE[id]
、POINT[id, x, y, order, curve_id]
- 我不确定这是否是最优的,要从数据库中获取一条曲线,我需要加入 tables 并且在 POINT table 中会有很多点
2) 一条曲线=一排一排table
- 我会将所有数据存储在一个 table 中,例如像这样:CURVE[id, data] 其中数据可以格式为 "[[1,2],[2,2],[3 ,4] ...]"(字符串)或作为 blob 或类似的东西。
你怎么看?还有其他选择吗?
我建议将你的数据点存储在单独的行中,你只需要一个额外的索引来排序它们。
您可以使用 GROUP_CONCAT()
函数重新创建您建议的字符串。
您的 table 将具有以下 结构 :
- curve_id
- point_id
- x_coord
- y_coord
查询看起来像:
--- {[1,2], [2,3] ...}
SELECT GROUP_CONCAT(CONCAT_WS("[", x_coord, ",", y_coord, "]"))
FROM table
WHERE curve_id ORDER BY point_id
您可以将曲线点存储在具有 JSON 数据类型的单个属性中。
您可以使用 javax.persistence.AttributeConverter 并像这样创建曲线转换器:
public class CurveConverter implements AttributeConverter<Curve, String> {
private static final String SEPARATOR1 = ",";
private static final String SEPARATOR2 = ";";
@Override
public String convertToDatabaseColumn(Curve curve) {
if (curve == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for(CurvePoint curvePoint:curve.getPoints()){
sb.append(curvePoint.getTorque());
sb.append(SEPARATOR1);
sb.append(curvePoint.getSpeed());
sb.append(SEPARATOR2);
}
sb.setLength(sb.length() - SEPARATOR2.length());
return sb.toString();
}
@Override
public Curve convertToEntityAttribute(String dbData) {
if (dbData == null || dbData.isEmpty()) {
return null;
}
String[] pieces = dbData.split(SEPARATOR2);
if (pieces == null || pieces.length == 0) {
return null;
}
List<CurvePoint> curvePoints = new ArrayList<>();
for(String piece:pieces){
String[] numbers = piece.split(SEPARATOR1);
curvePoints.add(new CurvePoint(Float.parseFloat(numbers[0]), Float.parseFloat(numbers[1])));
}
return Curve.builder().points(curvePoints).build();
}
}
这会将您的曲线作为字符串 (CSV - "1.1,2.2;3.3,4.4 ...") 作为一个属性存储到 table。你会摆脱关节,它会更快。这仅在曲线为 immutable(所有点同时变化)
时才有用
然后你只需在使用曲线的实体中的字段上添加注释,如下所示:
@Column(name = "curve", length = 10000)
@Basic(fetch = FetchType.LAZY)
@Convert(converter = CurveConverter.class)
Curve curve;
这里重要的是设置正确的字符串长度。还要检查 @Basic(fetch = FetchType.LAZY)
是否用于延迟加载曲线数据(仅在我们需要时)。注释 @Convert(converter = CurveConverter.class)
然后说要休眠,在将此字段保存到数据库之前,它将使用我们新创建的曲线 CurveConvertor 进行转换(与我们从数据库获取数据时相同)。
请问如何将曲线存储到数据库中。曲线对象由点数组表示。
我有两个选择:
1) 创建两个 tables,一个用于曲线,一个用于点
- 看起来像这样:
CURVE[id]
、POINT[id, x, y, order, curve_id]
- 我不确定这是否是最优的,要从数据库中获取一条曲线,我需要加入 tables 并且在 POINT table 中会有很多点
2) 一条曲线=一排一排table
- 我会将所有数据存储在一个 table 中,例如像这样:CURVE[id, data] 其中数据可以格式为 "[[1,2],[2,2],[3 ,4] ...]"(字符串)或作为 blob 或类似的东西。
你怎么看?还有其他选择吗?
我建议将你的数据点存储在单独的行中,你只需要一个额外的索引来排序它们。
您可以使用 GROUP_CONCAT()
函数重新创建您建议的字符串。
您的 table 将具有以下 结构 :
- curve_id
- point_id
- x_coord
- y_coord
查询看起来像:
--- {[1,2], [2,3] ...}
SELECT GROUP_CONCAT(CONCAT_WS("[", x_coord, ",", y_coord, "]"))
FROM table
WHERE curve_id ORDER BY point_id
您可以将曲线点存储在具有 JSON 数据类型的单个属性中。
您可以使用 javax.persistence.AttributeConverter 并像这样创建曲线转换器:
public class CurveConverter implements AttributeConverter<Curve, String> {
private static final String SEPARATOR1 = ",";
private static final String SEPARATOR2 = ";";
@Override
public String convertToDatabaseColumn(Curve curve) {
if (curve == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for(CurvePoint curvePoint:curve.getPoints()){
sb.append(curvePoint.getTorque());
sb.append(SEPARATOR1);
sb.append(curvePoint.getSpeed());
sb.append(SEPARATOR2);
}
sb.setLength(sb.length() - SEPARATOR2.length());
return sb.toString();
}
@Override
public Curve convertToEntityAttribute(String dbData) {
if (dbData == null || dbData.isEmpty()) {
return null;
}
String[] pieces = dbData.split(SEPARATOR2);
if (pieces == null || pieces.length == 0) {
return null;
}
List<CurvePoint> curvePoints = new ArrayList<>();
for(String piece:pieces){
String[] numbers = piece.split(SEPARATOR1);
curvePoints.add(new CurvePoint(Float.parseFloat(numbers[0]), Float.parseFloat(numbers[1])));
}
return Curve.builder().points(curvePoints).build();
}
}
这会将您的曲线作为字符串 (CSV - "1.1,2.2;3.3,4.4 ...") 作为一个属性存储到 table。你会摆脱关节,它会更快。这仅在曲线为 immutable(所有点同时变化)
时才有用然后你只需在使用曲线的实体中的字段上添加注释,如下所示:
@Column(name = "curve", length = 10000)
@Basic(fetch = FetchType.LAZY)
@Convert(converter = CurveConverter.class)
Curve curve;
这里重要的是设置正确的字符串长度。还要检查 @Basic(fetch = FetchType.LAZY)
是否用于延迟加载曲线数据(仅在我们需要时)。注释 @Convert(converter = CurveConverter.class)
然后说要休眠,在将此字段保存到数据库之前,它将使用我们新创建的曲线 CurveConvertor 进行转换(与我们从数据库获取数据时相同)。