Подтвердить что ты не робот

Комплексный SQL-запрос с подключением к лифтовой платформе

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

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

Спасибо заранее.


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

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

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

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

4b9b3361

Ответ 1

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

Экстраполируется из 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  
}  

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

// HasManyThrough for Many-to-Many Relationships  
class Employee ... {  
  object departmentids extends HasManyThrough(this, DepartmentId,   
    DepartmentIdTag, DepartmentIdTag.departmentid, DepartmentIdTag.Employee)  
}  

Ответ 2

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

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

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

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

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

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

Ответ 3

Вы всегда можете запускать любой запрос, который вам нравится, с помощью exec или runQuery: http://scala-tools.org/mvnsites/liftweb-2.4-M1/#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
}

Ответ 4

Ну, я ничего не знаю о Displayweb mapper, но что касается 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;

Ответ 5

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

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