Если у вас есть внешний ключ, который ссылается на неосновной ключ, вы должны использовать свойство-ref-атрибут
Его документация
Имя свойства связанного класса который присоединяется к этому внешнему ключу
И поскольку ваша Коллекция является неизменной , вы должны установить атрибут mutable в false
Здесь идет ваше отображение
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--Set up your package right here-->
<hibernate-mapping package="br.com.ar">
<class name="Aa" table="A">
<id name="id">
<generator class="native"/>
</id>
</class>
<class name="Bb" table="B">
<id name="id">
<generator class="native"/>
</id>
<many-to-one name="aa" column="A_ID" class="Aa"/>
</class>
<class name="Cc" table="C">
<id name="id">
<generator class="native"/>
</id>
<many-to-one name="aa" column="A_ID" class="Aa"/>
<bag name="bbList" table="B" mutable="false">
<key column="A_ID" property-ref="aa"/>
<one-to-many class="Bb"/>
</bag>
</class>
</hibernate-mapping>
Каждый класс описывается следующим образом
br.com.ar.Aa
public class Aa {
private Integer id;
// getter's and setter's
}
br.com.ar.Bb
public class Bb {
private Integer id;
private Aa aa;
// getter's and setter's
}
br.com.ar.Cc
public class Cc {
private Integer id;
private Aa aa;
private Collection<Bb> bbList = new ArrayList<Bb>();
// getter's and setter's
}
ДОБАВЛЕНО В КАЧЕСТВО РАБОТЫ
Хорошо, давайте посмотрим первый вариант использования
query = new StringBuilder().append("SELECT ")
.append("{cc.*} ")
.append("from ")
.append("C cc ")
.append("where ")
.append("cc.id = 1 ")
.toString();
Вы сказали
Объект загружен всеми данными и объектами, связанными с Bb .С этим объектом мы можем работать, изменять его и обновлять модификации в базе данных
Как видите, ваш NATIVE SQL просто получает объекты Cc. Нет присоединиться.Но вы сказали, что он извлекает все связанные объекты, включая The bbList.Если это так, то это происходит потому, что у вас есть такое отображение (Notice fetch = "select" lazy = "false")
<class name="Cc" table="C">
...
<bag name="bbList" table="B" mutable="false" fetch="select" lazy="false">
<key column="A_ID" property-ref="aa"/>
<one-to-many class="Bb"/>
</bag>
</class>
fetch = "select" использует дополнительный выбор.Для отношения «один ко многим» и «многие ко многим» (bbList, верно ???) атрибут fetch работает в сочетании с с атрибутом lazy, чтобы определить, как и когда загружается связанная коллекция.Если lazy = "true", то коллекция загружается, когда к ней обращается приложение, но если lazy = "false", то Hibernate загружает коллекцию немедленно , используя отдельный оператор SQL SELECT.
Но если запустить
query = new StringBuilder().append("SELECT ")
.append("{cc.*} ")
.append("from ")
.append("C cc ")
.append("where ")
.append("cc.id in (1,2) ")
.toString();
Я получаю ожидаемое
org.hibernate.HibernateException: коллекция не связана ни с одним сеансом
Почему ???
Вы хотите присоединиться к Cc и связанному с ним bbList через столбец A_ID , что подразумевает использование атрибута property-ref , верно ???
<class name="Cc" table="C">
...
<bag name="bbList" table="B" mutable="false" fetch="select" lazy="false">
<key column="A_ID" property-ref="aa"/>
<one-to-many class="Bb"/>
</bag>
</class>
Это происходит, если вы хотите использовать A_ID в качестве первичного ключа, Он должен быть уникальным .Поскольку существует множество свойств с тем же значением , вы получите это исключение.Первый вариант использования не выдает никаких исключений, потому что вы только что получили один объект
Обходной путь
Попробуйте получить одно за другим
List<Cc> resultList = new ArrayList<Cc>();
for (Integer id : new Integer[] {1, 2}) {
query = new StringBuilder().append("SELECT ")
.append("{cc.*} ")
.append("from ")
.append("C cc ")
.append("where ")
.append("cc.id = :id ")
.toString();
resultList.addAll(
session.createSQLQuery(query)
.addEntity("cc", Cc.class)
.setParameter("id", id)
.list());
}
Или использовать простые запросы JDBC