Сложный SQL-запрос с Join In Liftweb - PullRequest
13 голосов
/ 12 декабря 2011

Я хотел бы знать, есть ли способ выполнить некоторые сложные запросы SQL с помощью Mapper в Liftweb.

На самом деле, я хотел бы выполнить запрос соединения из баз данных. Сотрудники и департаменты, используятот факт, что они связаны отношениями 1-ко-многим.Другой пример также приветствуется.

Заранее спасибо.


Вот еще несколько деталей: Предположим, у меня есть 2 таблицы:

Employee : birthday, department ID, salary
Department : department ID, budget, address

Теперь я хотел бы получить списокобъект Employee (созданный с помощью Mapper), который имеет salary > 10$ и department budget < 100$.

Конечно, мой исходный код гораздо сложнее, но моя цель - иметь возможность иметь список отображенных объектов (т.е. Employee), соответствующий критериям в его собственной таблице или в связанной таблице.

Ответы [ 5 ]

4 голосов
/ 14 февраля 2012

Я посмотрел это. Похоже, что соединения выполняются на уровне объекта.

Экстраполировано от http://exploring.liftweb.net/master/index-8.html до вашего случая:

// Accessing foreign objects  
class Employee extends LongKeyedMapper[Employee] with IdPK {  
 ...  
  object department extends MappedLongForeignKey(this, Department)  
  def departmentName =  
    Text("My department is " + (department.obj.map(_.name.is) openOr "Unknown"))  
}  

class Department ... {  
  ...  
  def entries = Employee.findAll(By(Employee.department, this.id))  
}  

Если вы хотите выполнить сопоставление «многие ко многим», вам нужно предоставить собственное
Класс «join» с внешними ключами для ваших сопоставленных объектов.

// DepartmentId Entity  
class DepartmentId extends LongKeyedMapper[DepartmentId] with IdPK {  
  def getSingleton = DepartmentId  
  object name extends MappedString(this,100)  
}  
object DepartmentId extends DepartmentId with LongKeyedMetaMapper[DepartmentId] {  
  override def fieldOrder = List(name)  
}  

Далее мы определяем нашу сущность соединения, как показано ниже.
Это LongKeyedMapper, как и все остальные объекты,
но он содержит только поля внешнего ключа для других объектов.

// Join Entity  
class DepartmentIdTag extends LongKeyedMapper[DepartmentIdTag] with IdPK {  
  def getSingleton = DepartmentIdTag  
  object departmentid extends MappedLongForeignKey(this,DepartmentId)  
  object Employee extends MappedLongForeignKey(this,Employee)  
}  
object DepartmentIdTag extends DepartmentIdTag with LongKeyedMetaMapper[DepartmentIdTag] {  
  def join (departmentid : DepartmentId, tx : Employee) =  
    this.create.departmentid(departmentid).Employee(tx).save  
}  

Чтобы использовать объект объединения, вам нужно создать новый экземпляр и установить
соответствующие внешние ключи для указания на связанные экземпляры. Как видите,
для этого мы определили удобный метод для нашего мета-объекта Expense.
Чтобы сделать многие-ко-многим доступными в качестве поля на наших объектах, мы можем использовать
Черта HasManyThrough, как показано ниже

// HasManyThrough for Many-to-Many Relationships  
class Employee ... {  
  object departmentids extends HasManyThrough(this, DepartmentId,   
    DepartmentIdTag, DepartmentIdTag.departmentid, DepartmentIdTag.Employee)  
}  
1 голос
/ 15 февраля 2012

Вы всегда можете выполнить любой запрос с помощью exec или runQuery: http://scala -tools.org / mvnsites / liftweb-2,4-М1 / # net.liftweb.db.DB Хотя в Mapper можно делать и объединения.

Вы можете использовать OneToMany или ManyToMany черты

Чтобы использовать ManyToMany, вы должны указать поля для присоединения. Смотрите пример кода:

class Meeting extends LongKeyedMapper[Meeting] with IdPK with CreatedUpdated with OneToMany[Long, Meeting] with ManyToMany {
  def getSingleton = Meeting

  object owner extends MappedLongForeignKey(this, User)
  object title extends MappedString(this, 100)
  object beginDate extends MappedDateTime(this)
  object endDate extends MappedDateTime(this)
  object location extends MappedString(this,100)
  object description extends MappedText(this)
  object allDay extends MappedBoolean(this)
  object users extends MappedManyToMany(MeetingUser, MeetingUser.meeting, MeetingUser.user, User)
  object contacts extends MappedManyToMany(MeetingContact, MeetingContact.meeting, MeetingContact.contact, Contact)
}

А вот и объединяющаяся сущность.

class MeetingContact extends LongKeyedMapper[MeetingContact] with IdPK with CreatedUpdated {
  def getSingleton = MeetingContact
  object meeting extends MappedLongForeignKey(this, Meeting)
  object contact extends MappedLongForeignKey(this, Contact)
}

object MeetingContact extends MeetingContact with LongKeyedMetaMapper[MeetingContact] {
  def join(m: Meeting, c: Contact) = this.create.meeting(m).contact(c).save
  def assignedTo(c: Contact) = this.findAll(By(MeetingContact.contact, c)).filter(_.meeting.obj.isDefined).map(_.meeting.obj.open_!)
  override def beforeCreate() = MailSender.sendInviteToMeetingContact _ ::      super.beforeCreate
}
1 голос
/ 14 февраля 2012

Я заметил, что отдел написан двумя способами: отдел отдела

Возможно, картограф не знает, как составить список * результатов операции соединения
Вы пробовали следующее

SELECT 
  e.birthday     as birthDay     , 
  e.departmentId as departmentId ,
  e.salary       as salary
FROM 
  Employee e 
    INNER JOIN Department d 
    ON e.departmentId = d.departmentId
WHERE 
    d.budget < 100 AND 
    e.salary > 10

Отказ от ответственности: у меня 0 опыта работы с Mapper / Lift, но у меня есть опыт сопоставления наборов результатов запросов с объектами в Borland C ++ Builder, Delphi и Java.Некоторые из этих объектно-ориентированных систем содержат ошибки и не могут распространять SELECT * на все поля, поэтому вам нужно ТОЧНО сообщить им, какие поля получить.

В вашем случае у вас есть e.departmentId и d..departmentId, который может запутать Mapper в том, что он не знает, какой из них является реальным отделом в *.Некоторые системы на самом деле возвращают DepartmentId и DepartmentId_1 (эта система по умолчанию возвращает _1 в конец). Другие системы просто зависают, выдают ошибки, ведут себя непредсказуемо.

Я также видел существование или отсутствиесуществование прекращения ';'символ в конце может быть проблемой в некоторых стандартных приложениях SQL.

0 голосов
/ 08 февраля 2012

SQL выглядит следующим образом.

SELECT * 
FROM Employee e 
    INNER JOIN Department d 
        ON e.departmentId = d.departmentId
WHERE d.budget < 100 AND e.salary > 10
0 голосов
/ 28 января 2012

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

select e.birthday, e.department_id, e.salary from 
employee e left join department d on d.department_id=e.department_id
where d.budget>100 and e.salary>10;
...