Slick: читать значения, допускающие значение NULL, как вариант, когда левое соединение

Проблема при использовании Slick для присоединения: у меня есть 2 таблицы User и UserInfo, и я хочу оставить их, чтобы получить информацию о пользователе. Я пробовал это:

val q = for{
  (user,info) <- User leftJoin UserInfo on (_.id === _.userid)
} yield(user, info)

Но в таблице UserInfo есть поле, допускающее значение NULL, поэтому, когда я пытаюсь выполнить запрос:

q.map(user_info => (user_info._1,user_info._2)).list

Это делает ошибку, потому что user_info._2 имеет некоторые нулевые значения. Я знаю решение, которое дает каждое поле в UserInfo и добавляет getOrElse(None) для полей, допускающих значение NULL. Однако в UserInfo много полей, поэтому я не хочу их использовать.

Может кто-нибудь помочь мне?


person Kaka Hoang Huy    schedule 03.07.2014    source источник
comment
Если поля, допускающие значение NULL, определены как Options в схеме, они будут возвращены, поэтому я подозреваю, что ваша проблема в другом месте, например, какое именно исключение вы получаете? Как определяется ваша схема?   -  person Ende Neu    schedule 03.07.2014
comment
x.getOrElse(None) должно быть точно таким же, как x, верно? Как это может решить вашу проблему?   -  person Dan Getz    schedule 03.07.2014
comment
Дубликат stackoverflow.com/q/20386593 и stackoverflow.com/q/14990365   -  person Dan Getz    schedule 03.07.2014


Ответы (1)


Что вы МОЖЕТЕ сделать, так это определить функцию, которая выполняет преобразование, а затем использовать ее на своей карте:

def nullToOption[A](input: A): Option[A] = input match {
  case null => None
  case x    => Some(x)
}

А затем вы просто используете его в своей карте.

Я сделал простой пример, используя простой список:

val lst = List("Hello", null, "hi", null)

val newlst = map lst nullToOption

newList теперь выглядит следующим образом: List(Some("Hello"), None, Some("hi"), None)

Конечно, вы можете изменить nullToOption в соответствии с вашими потребностями; вот версия, которая принимает кортежи:

def nullToOption[A, B](input: (A,B)): (Option[A], Option[B]) = input match {
  case (x, y)       => (Some(x), Some(y))
  case (x, null)    => (Some(x), None)
  case (null, y)    => (None, Some(y))
  case (null, null) => (None, None)
}
person Electric Coffee    schedule 03.07.2014
comment
Ваш nullToOption для аргумента, не являющегося кортежем, уже существует в стандартной библиотеке как Option.apply (Option(...)). - person Dan Getz; 03.07.2014
comment
Я этого не знал, я просто написал это с головы - person Electric Coffee; 03.07.2014