kuros / random-jpa

Create random test data for JPA/Hibernate entities.
GNU General Public License v3.0
26 stars 4 forks source link

Create data of entities at the same level #26

Closed jeremylima closed 6 years ago

jeremylima commented 6 years ago

For example I have this tables:

Relations: 1 Invoice -> N InvoiceDetails 1 Invoice -> N InvoiceTrack

I want generate 1 Invoice and 2 InvoiceDetails and 2 InvoiceTrack in the same plan. I understood that it's a tree structure, so I don't know if my intent is posible.

I expected something like this:

└── *ROOT*
    └── (h=1) Invoice|0
        ├── (h=0) InvoiceDetails|0
        ├── (h=0) InvoiceDetails|1
    ├── (h=0) InvoiceTrack|2
    ├── (h=0) InvoiceTrack|3

My Links:

    links.add(Link.newLink(InvoiceDetails_.id, Invoice_.details));
        links.add(Link.newLink(InvoiceTrack_.id, Invoice_.track));

My Creation Plan:

 final JPAContext jpaContext = JPAContextFactory
                .newInstance(Database.POSTGRES, entityManager)
                .with(dependencies)
                .generate();

final CreationPlan creationPlan = jpaContext.create(
                Entity.of(Invoice.class)
                Entity.of(InvoiceDetails.class, 2),
                Entity.of(InvoiceTrack.class, 2)
        );

Output:

└── *ROOT*
    └── (h=1) Invoice|0
        ├── (h=0) InvoiceDetails|0
        │   ├── (h=0) InvoiceTrack|0
        │   └── (h=0) InvoiceTrack|1
        └── (h=0) InvoiceDetails|1
            ├── (h=0) InvoiceTrack|2
            └── (h=0) InvoiceTrack|3
kuros commented 6 years ago

This is the way currently random-jpa has been designed. Basically, it generates an ordered list of hierarchy and explode it to generate items. Dependency Graph --> List (Topographical sort) --> Tree So in this case it generates one Invoice with 2 InvoiceDetails & 2 InvoiceTrack each under its parent (InvoiceDetails). In this case if you will observe, InvoiceDetails & InvoiceTrack both has h=0 (height level)

└── *ROOT*
    └── (h=1) Invoice|0
        ├── (h=0) InvoiceDetails|0
        │   ├── (h=0) InvoiceTrack|0
        │   └── (h=0) InvoiceTrack|1
        └── (h=0) InvoiceDetails|1
            ├── (h=0) InvoiceTrack|2
            └── (h=0) InvoiceTrack|3

This basically means all the entities are at same level, but during sorting InvoiceDetails is followed by InvoiceTrack. Hence, when you say wanted to create only 2 invoiceTrack, the system generates 2 invoiceTrack under each InvoiceDetails. To solve this you simply have do this

final CreationPlan creationPlan = jpaContext.create(
                Entity.of(Invoice.class)
                Entity.of(InvoiceDetails.class, 2),
                Entity.of(InvoiceTrack.class, 1)
        );

This would run and will generate below structure:

└── *ROOT*
    └── (h=1) Invoice|0
        ├── (h=0) InvoiceDetails|0
        │   ├── (h=0) InvoiceTrack|0
        └── (h=0) InvoiceDetails|1
            └── (h=0) InvoiceTrack|1

But you might also get this result:

└── *ROOT*
    └── (h=1) Invoice|0
        └── (h=0) InvoiceTrack|0
              ├── (h=0) InvoiceDetails|0
              └── (h=0) InvoiceDetails|1

To make sure every time you generate the same hierarchy I have provided function createBefore() & createAfter():

final CreationPlan creationPlan = jpaContext.create(
                Entity.of(Invoice.class)
                Entity.of(InvoiceDetails.class, 2).createBefore(InvoiceTrack.class),
                Entity.of(InvoiceTrack.class, 1)
        );

Notice the height of the entities, it has changed:

└── *ROOT*
    └── (h=2) Invoice|0
        ├── (h=1) InvoiceDetails|0
        │   ├── (h=0) InvoiceTrack|0
        └── (h=1) InvoiceDetails|1
            └── (h=0) InvoiceTrack|1

Using createAfter & createBefore, is helpful when you have entities are at same height & you want to force order.

kuros commented 6 years ago

@jeremylima Please refer Updated Wiki