Сложный 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