2017-01-03 1 views
1

Ich verwende myBatis, um eine einfache Datenbank (als Beispiel) zuzuordnen.Mybatis verschachtelte Eins-zu-Eins- oder Eins-zu-viele-Beziehungen-Zuordnung

Es besteht aus 4 Modellen: Benutzer, Auto, Tarif, Insurance.

Benutzer hat private List carlist und privaten Tarif Tarif und einige andere Felder mit Getter und Setter.

Auto hat private Versicherung und einige anderen Felder mit Getter und Setter.

So kann ich nur 1. Verschachtelungsebene zuordnen. Ich meine, ich kann Benutzer und ihre Felder - Tarif und eine Liste von Autos zuordnen. Aber ich kann nicht Insurance Feld von Auto zuordnen. Was soll ich machen?

Hier ist meine mapper.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
<mapper namespace = "UserNamespace"> 
    <resultMap id="resultUser" type="User"> 
     <id property="id" column="id"/> 
     <result property="name" column="name"/> 
     <association property="tariff" column="tariff" select="getTariff" javaType="Tariff"/> 
     <collection property="carList" column="id" select="getCars" javaType="ArrayList" ofType="Car"> 
      <id property="id" column="id"/> 
      <result property="model" column="model"/> 
      <association property="insurance" column="insurance" select="getInsurance" javaType="Insurance"/> 
     </collection> 
    </resultMap> 

    <select id = "getAll" resultMap = "resultUser"> 
     SELECT * FROM carwashservice.users 
    </select> 

    <select id = "getTariff" parameterType="int" resultType="Tariff"> 
     SELECT tariffs.description FROM carwashservice.tariffs WHERE tariffs.id = #{id} 
    </select> 

    <select id = "getCars" parameterType="int" resultType="Car"> 
     SELECT * FROM carwashservice.cars WHERE cars.user = #{id} 
    </select> 

    <select id = "getInsurance" parameterType="int" resultType="Insurance"> 
     SELECT * FROM carwashservice.insurance WHERE insurance.id = #{insurance} 
    </select> 
</mapper> 

Und meine DB:

CREATE DATABASE IF NOT EXISTS `carwashservice` /*!40100 DEFAULT CHARACTER SET latin1 */; 

USE `carwashservice`; 

DROP TABLE IF EXISTS `cars`; 
CREATE TABLE `cars` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `model` VARCHAR(45) NOT NULL, 
    `user` INT(11) DEFAULT NULL, 
    `insurance` INT(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `user_idx` (`user`), 
    KEY `insurance_idx` (`insurance`), 
    CONSTRAINT `user` FOREIGN KEY (`user`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1; 

DROP TABLE IF EXISTS `insurance`; 
CREATE TABLE `insurance` (
    `id` INT(11) NOT NULL, 
    `cost` VARCHAR(45) NOT NULL, 
    `exp_date` VARCHAR(45) NOT NULL, 
    PRIMARY KEY (`id`), 
    CONSTRAINT `id` FOREIGN KEY (`id`) REFERENCES `cars` (`insurance`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

DROP TABLE IF EXISTS `tariffs`; 
CREATE TABLE `tariffs` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `description` VARCHAR(45) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `id` (`id`,`description`) 
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1; 

DROP TABLE IF EXISTS `users`; 
CREATE TABLE `users` (
    `id` INT(11) NOT NULL, 
    `name` VARCHAR(45) NOT NULL, 
    `tariff` INT(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `tariff_idx` (`tariff`), 
    KEY `id` (`id`,`name`), 
    CONSTRAINT `tariff` FOREIGN KEY (`tariff`) REFERENCES `tariffs` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 
+0

Welchen Fehler bekommen Sie? – Lucky

+0

Ich bekomme NullPointerException bei Zugriff auf Versicherungsfeld. Andere Felder, die korrekt mit Werten gefüllt sind. Versucht, dies durch JOIN-Select auf der gesamten Karte zu tun - das hat perfekt funktioniert, weil JOIN eine Tabelle erstellt und die Zuordnung einfach wird. Aber meine Hauptfrage ist immer noch aktuell. –

Antwort

0

Sie sollten das Auto-Mapping extrahieren: <collection property="carList" column="id" select="getCars" javaType="ArrayList" ofType="Car" />

In einem getrennten resultMap: <resultMap id="resultCar" type="Car"> <id property="id" column="id"/> <result property="model" column="model"/> <association property="insurance" column="insurance" select="getInsurance" javaType="Insurance"/> </resultMap>

An d referenzieren Sie es aus der Anweisung <select id = "getCars" parameterType="int" resultMap="resultCar">

Sie verwenden resultType="Car". Dies ist für die grundlegende Zuordnung in Ordnung, aber es gibt eine Verknüpfung mit Insurance: Dies ist nicht grundlegend und erfordert eine spezifische Zuordnung.

Darüber hinaus können die getCars Aussage seine eigene resultMap verwendet, dann, was Sie in carlist Sammlung definieren tatsächlich (out of scope) ignoriert. deshalb ist die Versicherungsliste null.

+0

Ich werde versuchen, was Sie gesagt haben, aber ich bin mir sicher - es besteht keine Notwendigkeit, eine weitere resultMap zu erstellen. Ich habe ein Beispiel für ein verschachteltes Mapping mit einer Ergebniskarte und einem sql-select gesehen. Zum Beispiel hier: http://www.programering.com/a/MDN5MjMwATg.html –

+0

Das von Ihnen angegebene Beispiel verwendet eine einzelne Auswahl mit Joins. Sie haben in einem früheren Kommentar angegeben, dass Sie das bereits erledigt haben und stattdessen den N + 1-Auswahlansatz mit _collection ** select = "getCars" verwenden möchten. ** _ – blackwizard

+0

Es tut mir leid. Hier ist, was ich meine: https://github.com/loiane/ibatis-handling-joins/blob/master/src/com/loiane/data/Blog.xml –