A Quick Start into Apache Cayenne

Setting up the Project

<dependency>
<groupId>org.apache.cayenne</groupId>
<artifactId>cayenne-server</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.14</version>
<scope>runtime</scope>
</dependency>
<plugin>
<groupId>org.apache.cayenne.plugins</groupId>
<artifactId>cayenne-modeler-maven-plugin</artifactId>
<version>4.0.1</version>
<configuration>
<modelFile>${project.basedir}/src/main/resources/cayenne-blog.xml</modelFile>
</configuration>
</plugin>

Mapping and Database Design

  • author: id (PK) and name
  • article: id (PK), title, content, and author_id (FK)
CREATE TABLE `author` (
`id` int(11) NOT NULL,
`name` varchar(250) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Indexes for table `article`
--
ALTER TABLE `article`
ADD PRIMARY KEY (`id`),
ADD KEY `author_id` (`author_id`);
--
-- Indexes for table `author`
--
ALTER TABLE `author`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for table `article`
--
ALTER TABLE `article`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `author`
--
ALTER TABLE `author`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- Constraints for table `article`
--
ALTER TABLE `article`
ADD CONSTRAINT `article_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`);
<plugin>
<groupId>org.apache.cayenne.plugins</groupId>
<artifactId>cayenne-maven-plugin</artifactId>
<version>4.0.1</version>
<configuration>
<map>${project.basedir}/src/main/resources/blog.map.xml</map>
<dataSource>
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://localhost:3306/cayenne_blog</url>
<username>root</username>
<password>root</password>
</dataSource>
<dbImport>
<defaultPackage>com.dassiorleando.apachecayenne.models</defaultPackage>
</dbImport>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
INFO] +++ Connecting: SUCCESS.
[INFO] Detected and installed adapter: org.apache.cayenne.dba.mysql.MySQLAdapter
[INFO] Table: cayenne_blog.AUTO_PK_SUPPORT
[INFO] Table: cayenne_blog.article
[INFO] Table: cayenne_blog.author
[INFO] Db Relationship : toOne (article.author_id, author.id)
[INFO] Db Relationship : toMany (author.id, article.author_id)
[INFO]
[INFO] Map file does not exist. Loaded db model will be saved into '/Users/dassiorleando/projects/opensource/apache-cayenne/src/main/resources/blog.map.xml'
[INFO]
[INFO] Detected changes:
[INFO] Create Table article
[INFO] Create Table author
[INFO] Create Table AUTO_PK_SUPPORT
[INFO]
[WARNING] Can't find ObjEntity for author
[WARNING] Db Relationship (Db Relationship : toOne (article.author_id, author.id)) will have GUESSED Obj Relationship reflection.
[INFO] Migration Complete Successfully.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.165 s
[INFO] Finished at: 2019-07-22T17:40:36+01:00
[INFO] Final Memory: 10M/164M
[INFO] ------------------------------------------------------------------------
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building apache-cayenne 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- cayenne-maven-plugin:4.0.1:cgen (default-cli) @ apache-cayenne ---
[INFO] Generating superclass file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/auto/_Article.java
[INFO] Generating class file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/Article.java
[INFO] Generating superclass file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/auto/_Author.java
[INFO] Generating class file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/Author.java
[INFO] Generating superclass file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/auto/_AutoPkSupport.java
[INFO] Generating class file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/AutoPkSupport.java
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
  • Cayenne-Generated: it manages the PK generation
  • Database-Generated: the PK is managed by the database engine
  • Custom Sequence: a custom logic needs to be implemented here
<?xml version="1.0" encoding="utf-8"?>
<domain project-version="9">
<map name="blog"/>
<node name="datanode"
factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
schema-update-strategy="org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy">
<map-ref name="blog"/>
<data-source>
<driver value="com.mysql.jdbc.Driver"/>
<url value="jdbc:mysql://localhost:3306/cayenne_blog"/>
<connectionPool min="1" max="1"/>
<login userName="root" password="root"/>
</data-source>
</node>
</domain>

Mapping Structure

  • DataNode(<node>): the database's model. It contains all information necessary to get connected to a database, such as the name of the database, the driver and the database user credentials.
  • DataMap(<data-map>): It's a container of persistent entities with their relations.
  • DbAttribute(<db-attribute>): represents a column in a database table.
  • DbEntity(<db-entity>): the model of a single database table or view. It can have DbAttributes and relationships.
  • ObjEntity(<obj-entity>): the model of a single persistent java class, which is made of ObjAttributes that correspond to entity class properties and ObjRelationships that are properties that have a type of another entity.
  • Embeddable(<embeddable>): the model of a Java class that acts as a property of an ObjEntity, but it corresponds to multiple columns in the database.
  • Procedure(<procedure>): to register stored procedure in the database.
  • Query(<query>): the model of a query, which is used to mapped query in configuration file without forget that we can also do it in the code.

Applying CRUD on Models

ServerRuntime cayenneRuntime = ServerRuntime.builder()
.addConfig("cayenne-blog.xml")
.build();
ObjectContext context = cayenneRuntime.newContext();

Creating an Object

/**
* Save an author
* @param name
*/
public void save(String name) {
// Save a single author
Author author = this.context.newObject(Author.class);
author.setName(name);
context.commitChanges();
}

Reading an Object

/**
* Find an author by its ID
* @param id the author's ID
* @return the matched author or null if not existing
*/
public Author findById(int id) {
Author author = Cayenne.objectForPK(context, Author.class, id);
return author;
}
/**
* Looking for an author by name
* @param name the name to look up with
* @return the first matched author or null if not existing
*/
public Author findByName(String name) {
Author foundAuthor = ObjectSelect.query(Author.class)
.where(Author.NAME.eq(name))
.selectOne(this.context);
return foundAuthor;
}
/**
* Find authors by name starting with(like%)
* @param partName expected name part
* @return list of authors
*/
public List<Author> findByNameLike(String partName) {
// Let's apply a case-insensitive LIKE on the Author's name column
// We get all the authors with their name starting with "partName"
List<Author> authorsLike = ObjectSelect.query(Author.class)
.where(Author.NAME.likeIgnoreCase(partName + "%"))
.select(context);
return authorsLike;
}
/**
* Find authors by name ending with
* @param partName expected name part
* @return list of authors
*/
public List<Author> findByNameEndWith(String partName) {
// All authors with names ending with "partName"
List<Author> authorsEnd = ObjectSelect.query(Author.class)
.where(Author.NAME.endsWith(partName))
.select(context);
return authorsEnd;
}

Finding all Records of a Class

public List<Author> findAll() {
// Looking for all authors
List<Author> authors = ObjectSelect
.query(Author.class)
.select(this.context);
return authors;
}

Updating an Object

/**
* Update an author
* @param id the author's ID
* @param newName the new name to set
* @return true for a successful operation and false unknown author
*/
public boolean update(int id, String newName) {
if (StringUtils.isEmpty(newName)) return false;
// Get the author to update
Author author = this.findById(id);
if (author == null) return false; // Set its name
author.setName(newName);
context.commitChanges();
return true;
}

Attach Relationship to an Object

/**
* Attach a fake article to the author
* @param id the author's ID
* @return true for a successful operation and false unknown author
*/
public boolean attachArticle(int id) {
// Get the author to link with
Author author = this.findById(id);
if (author == null) return false; // Create a fake article and link it to the current author
Article article = context.newObject(Article.class);
article.setTitle("My post title");
article.setContent("The content");
article.setAuthor(author);
context.commitChanges(); // Get author's linked data (articles)
List<Article> articles = author.getArticles();
return true;
}

Deleting an Object

/**
* Delete an author
* @param id author's ID
* @return true for a successful operation and false unknown author
*/
public boolean delete(int id) {
// Get the author to delete
Author author = this.findById(id);
if (author != null) {
context.deleteObjects(author);
context.commitChanges();
return true;
} else {
return false;
}
}

Deleting all records of a Class

// SQL delete queries for Author and Article classes
SQLTemplate deleteArticles = new SQLTemplate(Article.class, "delete from article");
SQLTemplate deleteAuthors = new SQLTemplate(Author.class, "delete from author");
// Applying the deletion queries
context.performGenericQuery(deleteArticles);
context.performGenericQuery(deleteAuthors);

Expression and ExpressionFactory

  • likeExp: used for building the LIKE expression.
  • likeIgnoreCaseExp: used to build the LIKE_IGNORE_CASE expression.
  • containsExp: an expression used for a LIKE query with the pattern matching anywhere in the string.
  • containsIgnoreCaseExp: similar to the containsExp but uses a case-insensitive approach.
  • startsWithExp: the pattern should match the beginning of the string.
  • startsWithIgnoreCaseExp: similar to the startsWithExp but it uses a case-insensitive approach.
  • endsWithExp: an expression that matches the end of a string.
  • endsWithIgnoreCaseExp: an expression that matches the end of a string that uses a case-insensitive approach.
  • expTrue: used for boolean true expressions.
  • expFalse: used for boolean false expressions.
  • andExp: used to chain two expressions with the and operator.
  • orExp: to chain two expressions using the or operator.

Conclusion

Original Source

--

--

--

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website:https://www.alibabacloud.com

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Industry use cases of Jenkins…

How To Create A Timeline To Track Your Achievements

Why should you integrate software? | LiveAgent

Using Swift Extensions To Clean Up Our Code

Core Java Programming Cheat Sheet — Introduction To Java Programming

Pragmatic Programmer

How I keep track of my Expenses as a Software Engineer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alibaba Cloud

Alibaba Cloud

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website:https://www.alibabacloud.com

More from Medium

Managing Data in Containers

Apache Kafka for beginners

9 Insanely Helpful Kafka Commands Every Developer Must Know

How I learn Structured Query Language (SQL)