Вы правы, что spring-data-r2dbc не является ORM. Он не отображает отношения в вашей базе данных. Что он может сделать, так это сопоставить строки вашей базы данных с объектами. Следующий фрагмент кода сопоставляется со строкой базы данных ниже:
Пример класса в Kotlin:
@Table("song")
class SongRow(
@Id val id: Long,
val name: String,
val artist: Long
)
Строка:
create table song(
id integer identity primary key,
artist integer references artist(id),
name varchar(100) NOT NULL,
);
Для способа автоматического получения столбцов в соответствии с вашей моделью см .: https://docs.spring.io/spring-data/r2dbc/docs/1.0.0.M1/reference/html/#mapping-usage
В ссылке выше также указано, что вы можете использовать @Column.
Что касается одного из ваших вопросов:
Какие варианты существуют или планируются для поддержки ORM в реактивных приложениях? Понятия не имею
blockquote>Что касается:
присоединяется при использовании spring-data-r2dbc
blockquote>Используя аннотацию @Query, вы может выполнять соединения. Если вы хотите отобразить данные, полученные с помощью объединений, вам лучше использовать DatabseClient (см. https://docs.spring.io/spring-data/r2dbc/docs/1.0.0.M1 /reference/html/#r2dbc.datbaseclient)
Проверьте этот FromBase32String
, реализация для.NET нашла здесь .
Редактирование: вышеупомянутая ссылка была битой; можно найти заархивированную копию в archive.org
фактическое чтение кода:
using System;
using System.Text;
public sealed class Base32 {
// the valid chars for the encoding
private static string ValidChars = "QAZ2WSX3" + "EDC4RFV5" + "TGB6YHN7" + "UJM8K9LP";
/// <summary>
/// Converts an array of bytes to a Base32-k string.
/// </summary>
public static string ToBase32String(byte[] bytes) {
StringBuilder sb = new StringBuilder(); // holds the base32 chars
byte index;
int hi = 5;
int currentByte = 0;
while (currentByte < bytes.Length) {
// do we need to use the next byte?
if (hi > 8) {
// get the last piece from the current byte, shift it to the right
// and increment the byte counter
index = (byte)(bytes[currentByte++] >> (hi - 5));
if (currentByte != bytes.Length) {
// if we are not at the end, get the first piece from
// the next byte, clear it and shift it to the left
index = (byte)(((byte)(bytes[currentByte] << (16 - hi)) >> 3) | index);
}
hi -= 3;
} else if(hi == 8) {
index = (byte)(bytes[currentByte++] >> 3);
hi -= 3;
} else {
// simply get the stuff from the current byte
index = (byte)((byte)(bytes[currentByte] << (8 - hi)) >> 3);
hi += 5;
}
sb.Append(ValidChars[index]);
}
return sb.ToString();
}
/// <summary>
/// Converts a Base32-k string into an array of bytes.
/// </summary>
/// <exception cref="System.ArgumentException">
/// Input string <paramref name="s">s</paramref> contains invalid Base32-k characters.
/// </exception>
public static byte[] FromBase32String(string str) {
int numBytes = str.Length * 5 / 8;
byte[] bytes = new Byte[numBytes];
// all UPPERCASE chars
str = str.ToUpper();
int bit_buffer;
int currentCharIndex;
int bits_in_buffer;
if (str.Length < 3) {
bytes[0] = (byte)(ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5);
return bytes;
}
bit_buffer = (ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5);
bits_in_buffer = 10;
currentCharIndex = 2;
for (int i = 0; i < bytes.Length; i++) {
bytes[i] = (byte)bit_buffer;
bit_buffer >>= 8;
bits_in_buffer -= 8;
while (bits_in_buffer < 8 && currentCharIndex < str.Length) {
bit_buffer |= ValidChars.IndexOf(str[currentCharIndex++]) << bits_in_buffer;
bits_in_buffer += 5;
}
}
return bytes;
}
}
Вот мое быстро кратко записанное решение. Это только работает над строками, которые являются кратными 8 base32 символам. Действительно работает, все же.
public class Base32
{
/// <summary>
/// Decode a Base32 string
/// This will only work on a multiple of 40 bits (5 bytes)
/// http://www.garykessler.net/library/base64.html
/// </summary>
public static byte[] Decode(string Base32String)
{
// Ignore hyphens
string str = Base32String.Replace("-", "");
// Convert it to bits
List<byte> bits = new List<byte>();
foreach (char c in str)
{
int i = CharToValue(c);
bits.Add((byte)((i & 16) > 0 ? 1 : 0));
bits.Add((byte)((i & 8) > 0 ? 1 : 0));
bits.Add((byte)((i & 4) > 0 ? 1 : 0));
bits.Add((byte)((i & 2) > 0 ? 1 : 0));
bits.Add((byte)((i & 1) > 0 ? 1 : 0));
}
// Convert bits into bytes
List<byte> bytes = new List<byte>();
for (int i = 0; i < bits.Count; i += 8)
{
bytes.Add((byte)(
(bits[i + 0] << 7) +
(bits[i + 1] << 6) +
(bits[i + 2] << 5) +
(bits[i + 3] << 4) +
(bits[i + 4] << 3) +
(bits[i + 5] << 2) +
(bits[i + 6] << 1) +
(bits[i + 7] << 0)));
}
return bytes.ToArray();
}
static int CharToValue(char c)
{
char cl = char.ToLower(c);
if (cl == 'a') return 0;
if (cl == 'b') return 1;
if (cl == 'c') return 2;
if (cl == 'd') return 3;
if (cl == 'e') return 4;
if (cl == 'f') return 5;
if (cl == 'g') return 6;
if (cl == 'h') return 7;
if (cl == 'i') return 8;
if (cl == 'j') return 9;
if (cl == 'k') return 10;
if (cl == 'l') return 11;
if (cl == 'm') return 12;
if (cl == 'n') return 13;
if (cl == 'o') return 14;
if (cl == 'p') return 15;
if (cl == 'q') return 16;
if (cl == 'r') return 17;
if (cl == 's') return 18;
if (cl == 't') return 19;
if (cl == 'u') return 20;
if (cl == 'v') return 21;
if (cl == 'w') return 22;
if (cl == 'x') return 23;
if (cl == 'y') return 24;
if (cl == 'z') return 25;
if (cl == '2') return 26;
if (cl == '3') return 27;
if (cl == '4') return 28;
if (cl == '5') return 29;
if (cl == '6') return 30;
if (cl == '7') return 31;
throw new Exception("Not a base32 string");
}
}
Я написал несколько гибких реализаций на основе стандартов различных методов кодирования/декодирования Base32 и Base64. В частности: base64url (согласно rfc4648) и его эквивалент base32.
По умолчанию класс Base32Url кодирует только символы от A до Z и от 2 до 7. Не используются дефисы, подчеркивания, плюсы, косые черты или знаки равенства, что делает его пригодным для использования в качестве маркера URL почти при любых обстоятельствах. Base32Url также поддерживает пользовательские алфавиты, чувствительность/нечувствительность к регистру, вставку/невставку и т.д.