<commit_before>== Lists in the data model

The proper handling of lists (many to one relations) in the database layer is quite important. Many application have performance
problems because they load too many objects from the database at the wrong time. For example a search by the
user may be slow only because for every found result all the depending objects are load too. Even if they
are not displayed on the result page.

Minimal-J separates two kind of list fields very strictly. The difference in the class definitions may
look small but the behavior is very different and should be know to developers.

IMPORTANT: It's very crucial if the elements of a list contain an id field or not. If they contain no id
they are closely tied to the object holding the list. Elements (objects) without id field cannot be changed, saved or
deleted directly or independently.

=== Elements with or without id<commit_msg>lists.adoc: more text<commit_after>= Lists in the data model

The proper handling of lists (many to one relations) in the database layer is quite important. Many application have performance
problems because they load too many objects from the database at the wrong time. For example a search by the
user may be slow only because for every found result all the depending objects are load too. Even if they
are not displayed on the result page.

Minimal-J separates two kind of list fields very strictly. The difference in the class definitions may
look small but the behavior is very different and should be know to developers.

IMPORTANT: It's very crucial if the elements of a list contain an id field or not. If they contain no id
they are closely tied to the object holding the list. Elements (objects) without id field cannot be changed, saved or
deleted directly or independently.

== Examples

=== Elements without id

In this example a person must have a first and a last name. But the person can also have many additional
names.

[source,java,title="Person.java"]
----
public class Person {
	public Object id;
	@Size(30) @NotEmpty
	public String lastName, firstName;
	public List<AdditionalName> additionalNames;
}
----

Additional names don't make sense without a person they are added. They don't have an id of their
own and can only be edited and saved in the context of a person

[source,java,title="AdditionalName.java"]
----
public class AdditionalName {
	@Size(30) @NotEmpty
	public String name;
}
----

=== Elements with an id

Maybe you want the person to have relations. You can for example store the children of
the person:

[source,java,title="Person.java"]
----
public class Person {
	public Object id;
	@Size(30) @NotEmpty
	public String lastName, firstName;
	public List<Person> children;
}
----

This class can be used like this:
----
public class PersonExample {

	public static void main(String[] args) {
		System.setProperty("java.util.logging.SimpleFormatter.format", "%5$s %6$s%n");

		Repository repository = new SqlRepository(DataSourceFactory.embeddedDataSource(), Person.class);
		
		AbstractTable.sqlLogger.setLevel(Level.FINEST);
		AbstractTable.sqlLogger.getParent().getHandlers()[0].setLevel(Level.FINEST);
		
		Person child1 = new Person();
		child1.firstName = "Markus";
		child1.lastName = "Stadler";
		
		child1.id = repository.insert(child1);

		Person parent = new Person();
		parent.firstName = "Max";
		parent.lastName = "Stadler";
		parent.children = Arrays.asList(child1);
		
		parent.id = repository.insert(parent);
		
		parent = repository.read(Person.class, parent.id);
		System.err.println(parent.children.getClass());
		System.err.println(parent.children.size());
		System.err.println(parent.children.get(0).firstName);
		System.err.println(parent.children.get(0).lastName);
	}
}
----

and get these results:
----
   20ms INSERT INTO PERSON (LAST_NAME, FIRST_NAME, id) VALUES ('Stadler', 'Markus', '52c678cd-1b6f-455b-beca-db71a8844d38') 
    0ms INSERT INTO PERSON (LAST_NAME, FIRST_NAME, id) VALUES ('Stadler', 'Max', '875e4b0c-cca4-4210-9bc1-a52a6fced3d8') 
    4ms INSERT INTO PERSON__CHILDREN (elementId, id, position) VALUES ('52c678cd-1b6f-455b-beca-db71a8844d38', '875e4b0c-cca4-4210-9bc1-a52a6fced3d8', 0) 
    6ms SELECT * FROM PERSON WHERE id = '875e4b0c-cca4-4210-9bc1-a52a6fced3d8' 
    6ms SELECT COUNT(*) FROM PERSON__CHILDREN WHERE id = '875e4b0c-cca4-4210-9bc1-a52a6fced3d8' 
class org.minimalj.repository.list.RelationList
1
    3ms SELECT T.* FROM PERSON T, PERSON__CHILDREN C WHERE T.id = C.elementId AND C.id = '875e4b0c-cca4-4210-9bc1-a52a6fced3d8' ORDER BY C.position OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY 
    0ms SELECT COUNT(*) FROM PERSON__CHILDREN WHERE id = '52c678cd-1b6f-455b-beca-db71a8844d38' 
Markus
    0ms SELECT T.* FROM PERSON T, PERSON__CHILDREN C WHERE T.id = C.elementId AND C.id = '875e4b0c-cca4-4210-9bc1-a52a6fced3d8' ORDER BY C.position OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY 
    0ms SELECT COUNT(*) FROM PERSON__CHILDREN WHERE id = '52c678cd-1b6f-455b-beca-db71a8844d38' 
Stadler
----

As you see a cross table 'PERSON__CHILDREN' is created. Cross tables don't have a corresponding Java class. the id field of such a table references
the id of the entity containing elements. The elementId is the id of the contained entity.

The class RelationList is used as a specialized list class for the children of a Person. RelationLists load their content lazy. Not all elements
are loaded when the parent entity is loaded. When a get method is called on the list the requested element is loaded by the backend. If you want avoid
too many server roundtrips and you know that a lot of elements will be requested you should use the subList method. The subList method of a RelationList
will return a unmodifiable List with all elements of the selected range preloaded. This is how such lists are used by the Frontend.

Again note that of course these are not the real sql statements. Prepared statements are use and the question marks are replaced with the
actual values when the statements are logged.

== Rule
{'fraction_non_alphanumeric': 0.07538691962056915, 'fraction_numerical': 0.034448327508736894, 'mean_word_length': 4.299823633156967, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6561053', 'n_tokens_mistral': 1932, 'n_tokens_neox': 1768, 'n_words': 778}