apache/cayenne

Mirror of Apache Cayenne

345

stars

7,491

commits

Java

primary language

Aug 30, 2026

updated

cayenne
database
java
library
network-client
network-server
web-framework
xml

README

Apache Cayenne

Maven Central Build Status

Apache Cayenne is an open source persistence framework for Java. With a wealth of unique and powerful features, Cayenne can address a wide range of persistence needs. Cayenne seamlessly binds one or more database schemas to Java objects, managing atomic commits and rollbacks, SQL generation, joins, sequences, and more.

Cayenne supports database reverse engineering and generation, as well as templated class generation. All of these functions can be controlled through the GUI CayenneModeler app. An entire database schema can be mapped directly to Java objects within minutes, all from the comfort of the GUI-based CayenneModeler.

Cayenne supports numerous other features, including caching, an object query syntax, relationship pre-fetching, on-demand object and relationship faulting, object inheritance, database auto-detection, and generic persistent objects. Cayenne can scale up or down to virtually any project size.

Quick Start

Create XML Mapping

Downloaded Cayenne Modeler from https://cayenne.apache.org/download/, start it and create a Cayenne project.

Include Cayenne in a Project

Maven

<dependencies>
    <dependency>
        <groupId>org.apache.cayenne</groupId>
        <artifactId>cayenne</artifactId>
        <version>5.0-M3</version>
    </dependency>
</dependencies>

Gradle

implementation 'org.apache.cayenne:cayenne:5.0-M3'

Create Cayenne Runtime

CayenneRuntime cayenneRuntime = CayenneRuntime.of()
    .addConfig("cayenne-demo.xml")
    .defaultDataNode(CayenneDataSource
             .of("jdbc:mysql://localhost:3306/cayenne_demo")
             .userName("username")
             .password("password")
             .build())
    .build();

Create New Objects

ObjectContext context = cayenneRuntime.newContext();

Artist picasso = context.newObject(Artist.class);
picasso.setName("Pablo Picasso");
picasso.setDateOfBirth(LocalDate.of(1881, 10, 25));

Gallery metropolitan = context.newObject(Gallery.class);
metropolitan.setName("Metropolitan Museum of Art");

Painting girl = context.newObject(Painting.class);
girl.setName("Girl Reading at a Table");

Painting stein = context.newObject(Painting.class);
stein.setName("Gertrude Stein");

picasso.addToPaintings(girl);
picasso.addToPaintings(stein);

girl.setGallery(metropolitan);
stein.setGallery(metropolitan);

context.commitChanges();

Queries

Select Objects

List<Painting> paintings = ObjectSelect.query(Painting.class)
        .where(Painting.ARTIST.dot(Artist.DATE_OF_BIRTH).year().lt(1900))
        .prefetch(Painting.ARTIST.joint())
        .select(context);

Exists Subqueries

long count = ObjectSelect.query(Artist.class)
    .where(Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE).like("painting%").exists())
    .selectCount(context);

Aggregate Functions

List<Object[]> artistAndPaintingCount = ObjectSelect
    .columnQuery(Artist.class, Artist.SELF, Artist.PAINTING_ARRAY.count())
    .where(Artist.ARTIST_NAME.like("a%"))
    .having(Artist.PAINTING_ARRAY.count().lt(5L))
    .orderBy(Artist.PAINTING_ARRAY.count().desc(), Artist.ARTIST_NAME.asc())
    .select(context);

for(Object[] next : artistAndPaintingCount) {
    Artist artist = (Artist)next[0];
    long paintingsCount = (Long)next[1];
    System.out.println(artist.getArtistName() + " has " + paintingsCount + " painting(s)");
}

Raw SQL Queries

// Selecting objects
List<Painting> paintings = SQLSelect
    .query(Painting.class, "SELECT * FROM PAINTING WHERE PAINTING_TITLE LIKE #bind($title)")
    .param("title", "painting%")
    .upperColumnNames()
    .localCache()
    .limit(100)
    .select(context);

// Selecting scalar values
List<String> paintingNames = SQLSelect
    .scalarQuery("SELECT PAINTING_TITLE FROM PAINTING WHERE ESTIMATED_PRICE > #bind($price)", String.class)
    .param("price", 100000)
    .select(context);

// Insert values
int inserted = SQLExec
    .query("INSERT INTO ARTIST (ARTIST_ID, ARTIST_NAME) VALUES (#bind($id), #bind($name))")
    .paramsArray(55, "Picasso")
    .update(context);

Collaboration and Support

Contributors

(top 30 of 46)

andrus

4,438 commits

stariy95

1,725 commits

aarrsseni

253 commits

thinline72

200 commits

apache/cayenne

Mirror of Apache Cayenne

345

stars

7,491

commits

Java

primary language

Aug 30, 2026

updated

cayenne
database
java
library
network-client
network-server
web-framework
xml

README

Apache Cayenne

Maven Central Build Status

Apache Cayenne is an open source persistence framework for Java. With a wealth of unique and powerful features, Cayenne can address a wide range of persistence needs. Cayenne seamlessly binds one or more database schemas to Java objects, managing atomic commits and rollbacks, SQL generation, joins, sequences, and more.

Cayenne supports database reverse engineering and generation, as well as templated class generation. All of these functions can be controlled through the GUI CayenneModeler app. An entire database schema can be mapped directly to Java objects within minutes, all from the comfort of the GUI-based CayenneModeler.

Cayenne supports numerous other features, including caching, an object query syntax, relationship pre-fetching, on-demand object and relationship faulting, object inheritance, database auto-detection, and generic persistent objects. Cayenne can scale up or down to virtually any project size.

Quick Start

Create XML Mapping

Downloaded Cayenne Modeler from https://cayenne.apache.org/download/, start it and create a Cayenne project.

Include Cayenne in a Project

Maven

<dependencies>
    <dependency>
        <groupId>org.apache.cayenne</groupId>
        <artifactId>cayenne</artifactId>
        <version>5.0-M3</version>
    </dependency>
</dependencies>

Gradle

implementation 'org.apache.cayenne:cayenne:5.0-M3'

Create Cayenne Runtime

CayenneRuntime cayenneRuntime = CayenneRuntime.of()
    .addConfig("cayenne-demo.xml")
    .defaultDataNode(CayenneDataSource
             .of("jdbc:mysql://localhost:3306/cayenne_demo")
             .userName("username")
             .password("password")
             .build())
    .build();

Create New Objects

ObjectContext context = cayenneRuntime.newContext();

Artist picasso = context.newObject(Artist.class);
picasso.setName("Pablo Picasso");
picasso.setDateOfBirth(LocalDate.of(1881, 10, 25));

Gallery metropolitan = context.newObject(Gallery.class);
metropolitan.setName("Metropolitan Museum of Art");

Painting girl = context.newObject(Painting.class);
girl.setName("Girl Reading at a Table");

Painting stein = context.newObject(Painting.class);
stein.setName("Gertrude Stein");

picasso.addToPaintings(girl);
picasso.addToPaintings(stein);

girl.setGallery(metropolitan);
stein.setGallery(metropolitan);

context.commitChanges();

Queries

Select Objects

List<Painting> paintings = ObjectSelect.query(Painting.class)
        .where(Painting.ARTIST.dot(Artist.DATE_OF_BIRTH).year().lt(1900))
        .prefetch(Painting.ARTIST.joint())
        .select(context);

Exists Subqueries

long count = ObjectSelect.query(Artist.class)
    .where(Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE).like("painting%").exists())
    .selectCount(context);

Aggregate Functions

List<Object[]> artistAndPaintingCount = ObjectSelect
    .columnQuery(Artist.class, Artist.SELF, Artist.PAINTING_ARRAY.count())
    .where(Artist.ARTIST_NAME.like("a%"))
    .having(Artist.PAINTING_ARRAY.count().lt(5L))
    .orderBy(Artist.PAINTING_ARRAY.count().desc(), Artist.ARTIST_NAME.asc())
    .select(context);

for(Object[] next : artistAndPaintingCount) {
    Artist artist = (Artist)next[0];
    long paintingsCount = (Long)next[1];
    System.out.println(artist.getArtistName() + " has " + paintingsCount + " painting(s)");
}

Raw SQL Queries

// Selecting objects
List<Painting> paintings = SQLSelect
    .query(Painting.class, "SELECT * FROM PAINTING WHERE PAINTING_TITLE LIKE #bind($title)")
    .param("title", "painting%")
    .upperColumnNames()
    .localCache()
    .limit(100)
    .select(context);

// Selecting scalar values
List<String> paintingNames = SQLSelect
    .scalarQuery("SELECT PAINTING_TITLE FROM PAINTING WHERE ESTIMATED_PRICE > #bind($price)", String.class)
    .param("price", 100000)
    .select(context);

// Insert values
int inserted = SQLExec
    .query("INSERT INTO ARTIST (ARTIST_ID, ARTIST_NAME) VALUES (#bind($id), #bind($name))")
    .paramsArray(55, "Picasso")
    .update(context);

Collaboration and Support

Contributors

(top 30 of 46)

andrus

4,438 commits

stariy95

1,725 commits

aarrsseni

253 commits

thinline72

200 commits

Languages

Java

99.8%