agentsclimarketplace

Bx orm relationships

Skill ortus-boxlang/skills/boxlang-modules/bx-orm/bx-orm-relationships

BoxLang AI skills repository and Claude Plugin

Install
npx -y skills add ortus-boxlang/skills --skill bx-orm-relationships

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use this skill when defining relationships between ORM entities: one-to-one, one-to-many, many-to-one, many-to-many, lazy loading, cascade options, foreign keys, link tables, singular names, and inverse relationships.

SKILL.md

6.3 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it

bx-orm: Entity Relationships

Relationship Overview

TypeUse CaseExample
one-to-oneSingle associated recordUser → Address
one-to-manyParent with collectionUser → Posts
many-to-oneChild pointing to parentPost → Author
many-to-manyBidirectional multiAuthor ↔ Book

Every relationship property uses fieldtype to declare its kind.

One-to-One

// Contact.bx — has one Address
class persistent="true" entityName="Contact" {

    property name="id"      fieldtype="id" generator="native";
    property name="name"    type="string";

    // One-to-one: each Contact has exactly one Address
    property name="address"
        fieldtype = "one-to-one"
        class     = "Address";

}

Set lazy="false" to eagerly load the related entity:

property name="address"
    fieldtype = "one-to-one"
    class     = "Address"
    lazy      = "false";

One-to-Many

// User.bx — has many Posts
class persistent="true" entityName="User" {

    property name="id"    fieldtype="id" generator="native";
    property name="email" type="string";

    // One-to-many: a User has many Posts
    property name="posts"
        fieldtype   = "one-to-many"
        class       = "Post"
        fkcolumn    = "author_id"   // FK column in the posts table
        lazy        = "true"
        singularName= "post";       // enables addPost(), removePost()

}

Accessing the collection:

user = entityLoadByPK( "User", 1 )
posts = user.getPosts()       // returns array of Post entities
user.addPost( newPost )       // uses singularName
user.removePost( oldPost )    // uses singularName
user.hasPosts()               // boolean

Many-to-One

// Post.bx — belongs to one Author (User)
class persistent="true" entityName="Post" {

    property name="id"    fieldtype="id" generator="native";
    property name="title" type="string";

    // Many-to-one: many Posts share one Author
    property name="author"
        fieldtype = "many-to-one"
        class     = "User"
        fkcolumn  = "author_id";

}
post   = entityLoadByPK( "Post", 42 )
author = post.getAuthor()     // returns User entity

Many-to-Many

// Author.bx — can write many Books; Books can have many Authors
class persistent="true" entityName="Author" {

    property name="id"   fieldtype="id" generator="native";
    property name="name" type="string";

    property name="books"
        fieldtype   = "many-to-many"
        class       = "Book"
        linktable   = "author_books"   // join table
        fkcolumn    = "author_id"      // this entity's FK in join table
        inversejoin = "book_id"        // other entity's FK in join table
        singularName= "book";

}
// Book.bx — inverse side
class persistent="true" entityName="Book" {

    property name="id"      fieldtype="id" generator="native";
    property name="title"   type="string";

    property name="authors"
        fieldtype   = "many-to-many"
        class       = "Author"
        linktable   = "author_books"
        fkcolumn    = "book_id"
        inversejoin = "author_id"
        singularName= "author";

}

Relationship Property Annotations

AnnotationDescription
fieldtypeRelationship type: one-to-one, one-to-many, many-to-one, many-to-many
classFULLY qualified path or entity name of the related class
fkcolumnForeign key column name
linktableJoin table name (many-to-many only)
inversejoinFK column for the other entity in the join table
lazy"true" (default) or "false" for eager loading
cascade"all", "save-update", "delete", "none"
singularNameSingular form — enables addX(), removeX(), hasX() methods
orderByDefault sort column(s) for collections
whereSQL WHERE clause to filter the collection
fetch"select" or "join" fetching strategy

Cascade Options

// Cascade save/delete to child records
property name="posts"
    fieldtype = "one-to-many"
    class     = "Post"
    fkcolumn  = "user_id"
    cascade   = "all";         // save, update, and delete cascade

// Cascade save only (not delete)
property name="address"
    fieldtype = "one-to-one"
    class     = "Address"
    cascade   = "save-update";
Cascade ValueBehavior
noneNo cascade
save-updateCascade save and update operations
deleteCascade delete only
allCascade save, update, and delete
all-delete-orphanall + delete orphaned records

Lazy vs Eager Loading

// Lazy (default) — related entity loaded only when accessed
property name="posts" fieldtype="one-to-many" class="Post" lazy="true";

// Eager — loads related entity in the same SQL query
property name="address" fieldtype="one-to-one" class="Address" lazy="false";

Recommendation: Use lazy="true" (default) for collections (one-to-many, many-to-many) and consider lazy="false" only for single-record relationships (one-to-one) where you always need the related data.

N+1 Problem Prevention

Use batchSize to batch-load related entities:

// Entity-level batchSize
class persistent="true" entityName="Post" batchSize="20" {
    // ...
}

// Relationship-level batchSize
property name="comments"
    fieldtype = "one-to-many"
    class     = "Comment"
    fkcolumn  = "post_id"
    batchSize = "20";

Common Pitfalls

  • ❌ Do NOT forget fkcolumn on one-to-many and many-to-one — Hibernate cannot infer it
  • ❌ Do NOT use lazy="false" on large collections — will load thousands of records
  • ❌ Do NOT forget linktable on many-to-many — it is required
  • ✅ Always set singularName on collection relationships for clean addX() / removeX() API
  • ✅ Use cascade="all-delete-orphan" on owned one-to-many collections (e.g., order → line items)
  • ✅ Define both sides of many-to-many relationships with matching linktable values

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 327,069. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.