bx-orm-relationships — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited bx-orm-relationships (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
| Type | Use Case | Example |
|---|---|---|
one-to-one | Single associated record | User → Address |
one-to-many | Parent with collection | User → Posts |
many-to-one | Child pointing to parent | Post → Author |
many-to-many | Bidirectional multi | Author ↔ Book |
Every relationship property uses fieldtype to declare its kind.
// 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";// 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// 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// 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";
}| Annotation | Description |
|---|---|
fieldtype | Relationship type: one-to-one, one-to-many, many-to-one, many-to-many |
class | FULLY qualified path or entity name of the related class |
fkcolumn | Foreign key column name |
linktable | Join table name (many-to-many only) |
inversejoin | FK column for the other entity in the join table |
lazy | "true" (default) or "false" for eager loading |
cascade | "all", "save-update", "delete", "none" |
singularName | Singular form — enables addX(), removeX(), hasX() methods |
orderBy | Default sort column(s) for collections |
where | SQL WHERE clause to filter the collection |
fetch | "select" or "join" fetching strategy |
// 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 Value | Behavior |
|---|---|
none | No cascade |
save-update | Cascade save and update operations |
delete | Cascade delete only |
all | Cascade save, update, and delete |
all-delete-orphan | all + delete orphaned records |
// 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.
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";fkcolumn on one-to-many and many-to-one — Hibernate cannot infer itlazy="false" on large collections — will load thousands of recordslinktable on many-to-many — it is requiredsingularName on collection relationships for clean addX() / removeX() APIcascade="all-delete-orphan" on owned one-to-many collections (e.g., order → line items)linktable values~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.