[JAVA] [MyBatis] Ich möchte eine Abfrageabfrage einer Tabelle zuordnen, die eine Eins-zu-Viele-Beziehung zu einer verschachtelten Bean hat.

Problem

Nehmen Sie als Beispiele Bug-Tracking-Systeme wie JIRA und Redmine. Dieses System erstellt für jedes Thema ein Projekt. Angenommen, für jedes Projekt wird ein Ticket erstellt, und Benutzer können das Ticket kommentieren. Das ER-Diagramm ist wie folgt.

image.png

Angenommen, die Daten sehen folgendermaßen aus:

image.png

Betrachten Sie nun das gesamte Projekt und die damit verbundenen Ticketkommentare. Es ist einfach, eine Abfrage zu schreiben, aber was ist, wenn Sie die Ergebnisse einer verschachtelten Java-Bean mit dem Namen "Project.java" zuordnen? Mit anderen Worten, eine Abfrageabfrage für eine Tabelle mit einer Eins-zu-Viele-Beziehung. Was ist, wenn ich einer verschachtelten Bean zuordnen möchte?

Project.java


@Data
@ToString(exclude = {"tickets"})
public class Project {
    private int projectId;
    private String name;
    private List<Ticket> tickets;
}

Ticket.java


@Data
@ToString(exclude = {"comments"})
public class Ticket {
    private int ticketId;
    private String content;
    private List<Comment> comments;
}

Comment.java


@Data
public class Comment {
    private int commentId;
    private String content;
}

Antworten

Verwenden Sie die Funktionen resultMap und collection. Erstellen Sie im obigen Beispiel die folgende XML.

ProjectMapper.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="com.example.demo.mapper.ProjectMapper">
  <select id="findAllProject" resultMap="findAllProjectResultMap">
    SELECT
      project.project_id,
      project.name as project_name,
      ticket.ticket_id,
      ticket.content as ticket_content,
      comment.comment_id,
      comment.content as comment_content
    FROM project
    JOIN ticket ON project.project_id = ticket.project_id
    JOIN comment ON ticket.ticket_id = comment.ticket_id
  </select>

  <resultMap id="findAllProjectResultMap" type="com.example.demo.dto.Project">
    <id property="projectId" column="project_id" />
    <result property="name" column="project_name"/>
    <collection property="tickets" ofType="com.example.demo.dto.Ticket">
      <id property="ticketId" column="ticket_id" />
      <result property="content" column="ticket_content"/>
      <collection property="comments" ofType="com.example.demo.dto.Comment">
        <id property="commentId" column="comment_id" />
        <result property="content" column="comment_content"/>
      </collection>
    </collection>
  </resultMap>
</mapper>

Im folgenden Code können Sie überprüfen, wie das Ergebnis der Ausführung von SQL von Pretty Print auf Java Bean abgebildet wird.

CommandlineappliApplication.java


@Component
public class CommandlineappliApplication implements CommandLineRunner{

    @Autowired
    private ProjectMapper projectMapper;

    @Override
    public void run(String... args) throws Exception {
        for (Project project : projectMapper.findAllProject()) {
            System.out.printf("%s%n", project);

            for (Ticket ticket : project.getTickets()) {
                System.out.printf("  └ %s%n", ticket);

                for (Comment comment : ticket.getComments()) {
                    System.out.printf("      └ %s%n", comment);
                }
            }
        }
    }
}

Das Ergebnis der tatsächlichen Operation ist wie folgt. Sie können sehen, dass das SQL-Ausführungsergebnis wie erwartet der verschachtelten Bean zugeordnet ist.

Project(projectId=1, name=Projekt 1)
  └ Ticket(ticketId=1, content=Ticket 1-1)
      └ Comment(commentId=1, content=Kommentar 1-1-1)
      └ Comment(commentId=2, content=Kommentar 1-1-2)
  └ Ticket(ticketId=2, content=Ticket 1-2)
      └ Comment(commentId=3, content=Kommentar 1-2-1)
      └ Comment(commentId=4, content=Kommentar 1-2-2)
Project(projectId=2, name=Projekt 2)
  └ Ticket(ticketId=3, content=Ticket 2-1)
      └ Comment(commentId=5, content=Kommentar 2-1-1)
      └ Comment(commentId=6, content=Kommentar 2-1-2)
  └ Ticket(ticketId=4, content=Ticket 2-2)
      └ Comment(commentId=7, content=Kommentar 2-2-1)
      └ Comment(commentId=8, content=Kommentar 2-2-2)

Umweltinformationen

pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>mybatis-sample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>mybatis-sample</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>11</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-batch</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.1.3</version>
		</dependency>

		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.batch</groupId>
			<artifactId>spring-batch-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Recommended Posts

[MyBatis] Ich möchte eine Abfrageabfrage einer Tabelle zuordnen, die eine Eins-zu-Viele-Beziehung zu einer verschachtelten Bean hat.
Ich möchte Swipeback auf einem Bildschirm verwenden, der XLPagerTabStrip verwendet
Ich möchte eine Webanwendung entwickeln!
Ich möchte ein schönes build.gradle schreiben
Ich möchte einen Unit Test schreiben!
[Android] Ich möchte einen ViewPager erstellen, der für Tutorials verwendet werden kann
[Ruby] Ich möchte einen Methodensprung machen!
Ich möchte eine einfache Wiederholung einer Zeichenkette schreiben
Ich möchte eine Struktur für die Ausnahmebehandlung entwerfen
Ich möchte eine Verbindung herstellen, wenn eine Datenbank mit Spring und MyBatis erstellt wird
Ich möchte PowerMock in einer Klasse verwenden, die parametrisierte Tests und gewöhnliche Tests kombiniert
7 Dinge, die du behalten sollst, damit es kein verdammter Code wird
Eine Geschichte, nach der ich süchtig war, als ich einen Schlüssel bekam, der automatisch auf MyBatis ausprobiert wurde
Ich möchte eine Methode einer anderen Klasse aufrufen
Gelernter Stream (Ich möchte List in Map <Integer, List> konvertieren)
Ich möchte ein kleines Symbol in Rails verwenden
Ich möchte eine bestimmte Datei mit WatchService überwachen
Ich möchte eine Funktion in der Rails Console definieren
Ich möchte Schlangenfälle mit Tabellendefinitionen stoppen
Ich möchte in RSpec auf einen GoogleMap-Pin klicken
Ich möchte eine generische Anmerkung für einen Typ erstellen
Ich möchte der Kommentarfunktion eine Löschfunktion hinzufügen
Ich möchte eine Schleife schreiben, die auf einen Index mit der Stream-API von Java 8 verweist