Допустим, у меня есть следующие объекты:
Магазин:
component
{
property name="Id" fieldtype="id" generator="native";
property name="Name";
property name="Fruits" fieldtype="one-to-many" cfc="Fruit" inverse="true" cascade="all-delete-orphan";
property name="Vegetables" fieldtype="one-to-many" cfc="Vegetable" inverse="true" cascade="all-delete-orphan";
}
Product.cfc
component table="Product" discriminatorcolumn="ProductType"
{
property name="Id" fieldtype="id" generator="native";
property name="Name";
property name="Price";
property name="Store" fieldtype="many-to-one" cfc="Store";
}
Fruit.cfc
component table="Product" extends="Product" discriminatorvalue="Fruit"
{
property name="HasVitaminC" type="boolean";
}
Vegetable.cfc
component table="Product" extends="Product" discriminatorvalue="Vegetable"
{
property name="IsGreen" type="boolean";
}
Другими словами, Store
содержит набор Fruits
и Vegetables
, а Fruits
и Vegetables
расширяют базовый компонент Product
. Я использую отображение таблицы на иерархию со столбцом дискриминатора для Products
.
Проблема, с которой я сейчас сталкиваюсь, заключается в том, что я заполняю магазин и пытаюсь получить коллекцию Fruits
или Vegetables
:
var store = EntityLoadByPK("Store", 13);
var fruits = store.getFruits();
SQL, который он работает за кулисами, чтобы захватить фрукты:
select * from Product where store_id = 13;
Как видите, дискриминатор не используется, и я получаю фрукты и овощи. Когда я пытаюсь перебрать эту коллекцию, я получу сообщение об ошибке, потому что Vegetable
- это несоответствие типов с Fruit
.
Однако, если я попробую обратный путь, где я начну с Fruit
и отфильтрую по Store
:
var store = EntityLoadByPK("Store", 13);
var fruits = EntityLoad("Fruit", {store=store});
Будет запущен правильный SQL:
select * from Product where ProductType = 'Fruit' and store_id = 13;
У меня вопрос , что я делаю здесь неправильно, что позволяет ORM работать правильно, когда я фильтрую фрукты по магазинам, но не правильно, когда я пытаюсь получить коллекцию фруктов для магазина? Или я наткнулся на ошибку?
Редактировать: Вот файл CFM, который я выполняю для воспроизведения этого поведения:
<cfscript>
ormReload();
// create a new store
store = EntityNew("Store");
store.setName("Grocery Store");
// create a new fruit and add it to the store
fruit = EntityNew("Fruit");
fruit.setName("Banana");
fruit.setStore(store);
store.addFruits(fruit);
// create a new vegetable and add it to the store
vegetable = EntityNew("Vegetable");
vegetable.setName("Asparagus");
vegetable.setStore(store);
store.addVegetables(vegetable);
// save the store
EntitySave(store);
// flush and clear out the session
ormFlush();
ormClearSession();
// load the store and get its fruits collection, this will execute the
// wrong SQL and return TWO items
store = EntityLoad("Store")[1];
fruits = store.getFruits();
writedump(fruits);
ormClearSession();
// load the store and filter fruits by it, this will execute the
// correct SQL and return only one item
store = EntityLoad("Store")[1];
fruits = EntityLoad("Fruit", {store=store});
writedump(fruits);
</cfscript>