Сложный SQL-запрос с Join в Liftweb

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

на самом деле то, что я хотел бы сделать, это выполнить запрос соединения от сотрудников баз данных и отделов, используя тот факт, что они связаны отношением 1 ко многим. Еще один пример также приветствуется.

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


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

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

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

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

5 ответов


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

экстраполировать от 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)  
}  

Далее мы определяем наш объект join, как показано ниже.
Это 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, вам нужно создать новый экземпляр и установить
соответствующие внешние ключи, указывающие на связанные экземпляры. Как видите,
мы определили удобный метод на нашем Метаобъекте расхода, чтобы сделать именно это.
Чтобы сделать многие-ко-многим доступным в качестве поля для наших сущностей, мы можем использовать
HasManyThrough черта, как показано ниже

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

Я заметил, что отдел пишется двумя способами: кафедра отдел

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

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 and d.departmentId, который может запутать картографа, не зная, какой из них является реальным departmentId в *. Некоторые системы фактически вернут departmentId и departmentId_1 (этот по умолчанию получает _1, прикрепленный к концу) Другие системы просто зависают, ошибаются, имеют непредсказуемое поведение.

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


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

Ну, я ничего не знаю о liftweb 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;

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

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