SansOrm

A "No-ORM" sane SQL <-> Java object mapping library

License

License

Categories

Categories

ORM Data
GroupId

GroupId

com.github.h-thurow
ArtifactId

ArtifactId

sansorm
Last Version

Last Version

3.8
Release Date

Release Date

Type

Type

jar
Description

Description

SansOrm
A "No-ORM" sane SQL <-> Java object mapping library
Project URL

Project URL

https://github.com/h-thurow/SansOrm
Source Code Management

Source Code Management

https://github.com/h-thurow/SansOrm.git

Download sansorm

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.h-thurow/sansorm/ -->
<dependency>
    <groupId>com.github.h-thurow</groupId>
    <artifactId>sansorm</artifactId>
    <version>3.8</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.h-thurow/sansorm/
implementation 'com.github.h-thurow:sansorm:3.8'
// https://jarcasting.com/artifacts/com.github.h-thurow/sansorm/
implementation ("com.github.h-thurow:sansorm:3.8")
'com.github.h-thurow:sansorm:jar:3.8'
<dependency org="com.github.h-thurow" name="sansorm" rev="3.8">
  <artifact name="sansorm" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.h-thurow', module='sansorm', version='3.8')
)
libraryDependencies += "com.github.h-thurow" % "sansorm" % "3.8"
[com.github.h-thurow/sansorm "3.8"]

Dependencies

compile (1)

Group / Artifact Type Version
javax.transaction : javax.transaction-api Optional jar 1.2

provided (5)

Group / Artifact Type Version
org.eclipse.persistence : javax.persistence jar 2.1.0
javax.transaction : transaction-api jar 1.1
org.slf4j : slf4j-api jar 1.7.25
org.apache.felix : maven-bundle-plugin Optional maven-plugin 2.3.7
org.postgresql : postgresql Optional jar 9.4-1206-jdbc42

test (6)

Group / Artifact Type Version
junit : junit jar 4.12
com.h2database : h2 jar 1.4.191
com.zaxxer : HikariCP jar 2.7.2
org.assertj : assertj-core jar 3.8.0
org.slf4j : slf4j-simple jar 1.7.25
org.xerial : sqlite-jdbc jar 3.20.1

Project Modules

There are no modules declared in this project.

q2o

q2o is a JPA based Java object mapper which helps you with many of the tedious SQL and JDBC ResultSet related tasks, but without all the complexity an ORM framework comes with. It offers limited support for reading object relations on demand, but it does not intend to be an ORM.

Intention of this fork

Support not only field access but property access to. With property access the class's getters and setters are called to read or write values. With field access the fields are read and written to directly. So if you need more control over the process of reading or writing set access type explicitely with @Access annotation or annotate getters, not fields (do not mix the style within one class). If there is no @Access annotation found the place of the annotations decide upon the access type. With support for property access you can also let IntelliJ generate your entity classes (IntelliJ defaults to annotating getters, not fields) and use them without reworking.

Support for reading @OneToOne and @ManyToOne relations on demand.

Spring Transaction Support.

MySQL Support (New in 3.13)

Automatic type conversion between java.util.Date or java.util.Calendar and DATE, TIME and TIMESTAMP fields via JPA's @Temporal annotation (New in 3.14)

More convenient methods.

API clean-up (still subject of change!). There is a SansOrm 3.7 compatibility layer.

Numerous tests added to stabilize further development.

Initialization

First of all we need a datasource. Once you get it, call one of q2o.initializeXXX methods:

DataSource ds = ...;
q2o.initializeTxSimple(ds);

// or if you do not want to use Transactions
q2o.initializeTxNone(ds);

// or if you have your own TransactionManager and UserTransaction
TransactionManager tm = ...;
UserTransaction ut = ...;
q2o.initializeTxCustom(ds, tm, ut);

// Starting with V 3.12 you can make q2o Spring transaction aware
q2o.initializeWithSpringTxSupport(ds);

// From V 3.13 on you can enable MySQL support. Configure MySQL with generateSimpleParameterMetadata=true, call 
// one of the q2o.initialize* methods and activate MySQL mode:
q2o.setMySqlMode(true);

For better understanding of these methods see also Transaction Management.

Even without initialization there is support for some q2o methods. This means all methods taking a Connection, PreparedStatement or ResultSet as an argument can be called without q2o having been initialized.

Object Mapping

Take this database table:

CREATE TABLE customer (
   customer_id INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY,
   last_name VARCHAR(255),
   first_name VARCHAR(255),
   email VARCHAR(255)
);

Let's imagine a Java class that reflects the table in a straight-forward way, and contains some JPA annotations. These annotations will instruct q2o how to map objects to SQL and ResultSets to Objects:

@Entity
@Table(name = "customer")
public class Customer {
   @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
   private int id;

   @Column(name = "last_name")
   private String lastName;

   @Column(name = "first_name")
   private String firstName;

   @Column(name = "email")
   private String emailAddress;

   public Customer() {
      // no arg constuctor declaration is necessary only when other constructors are declared
   }
}

Here we introduce the most important q2o classes, Q2Obj and Q2ObjList. Let's look at how they can help:

public List<Customer> getAllCustomers() {
   return Q2ObjList.fromClause(Customer.class, null);
}

As a second argument to Q2ObjList.fromClause() you can provide a where clause, to restrict the found objects:

Q2ObjList.fromClause(Customer.class, "id BETWEEN ? AND ?", minId, maxId)

Now lets store a new customer

Customer customer = new Customer();
customer.setFirstName = "...";
customer.setLastName = "...";
Q2Obj.insert(customer);

The very useful thing that happens here is that after storing the object you can immediately access its id:

assertTrue(customer.getId() != 0);

While you are working with the customer object "offline" the object might change in the database. How can you update your object so it reflects the current state?

customer = Q2Obj.refresh(customer)

Note that the returned customer object is identical with the one you supplied as argument or null in case it was deleted in the meantime.

What if your object has many fields and you only want to retrieve some of them?

Q2Obj.fromSelect(Customer.class, "select id, last_name from customer where id = ?", id)

As long as your object has the id set, you can refresh its values with refresh(customer) or change its values and update it with updateObject(customer).

There are much more useful methods like:

  • Q2Obj.byId(Class<T> type, Object... ids)
  • Q2Obj.update(customer)
  • Q2Obj.delete(customer)
  • Q2Obj.fromStatement(PreparedStatement stmt, Class<T> clazz, Object... args)
  • Q2Obj.countFromClause(Class<T> clazz, String clause, Object... args)

Many of these methods can also work with lists of objects. See Javadoc.

q2o and Spring

q2o is helpful even when you depend on Spring JDBC:

List<Customer> customers = jdbcTemplate.query("...", new RowMapper<Customer>() {
    @Override
    public Customer mapRow(final ResultSet rs, final int rowNum) throws SQLException {
        return Q2Obj.fromResultSet(rs, Customer.class);
    }
});

All q2o methods taking a Connection, PreparedStatement or ResultSet are throwing SQLExceptions, so Spring can translate them into some subtype of its DataAccessException. These methods can even be called without initialization of q2o.

Starting with V 3.12 you can initialize q2o with Spring Transaction support too. See Initialization above.

Supported Annotations

Annotation Supported elements Position
@Access           value (=AccessType.PROPERTY,AccessType.FIELD)           Classes, Getters, Fields
@Column           name, insertable, updatable, table   Getters, Fields
@Convert converter Getters, Fields
@Entity name Classes
@Enumerated value (=EnumType.ORDINAL, EnumType.STRING) Getters, Fields
@GeneratedValue strategy (GenerationType.IDENTITY only) Getters, Fields
@Id n/a Getters, Fields
@JoinColumn       name (supports only @OneToOne and @ManyToOne)     Getters, Fields
@MappedSuperclass n/a Classes
@Table name Classes
@Transient n/a Getters, Fields
@Temporal DATE, TIME, TIMESTAMP (New in 3.14) Getters, Fields

More Advanced

Transaction Management
Performing Joins
Help with raw JDBC
Automatic Data Type Conversions
Change log

Download

<dependency>
    <groupId>com.github.h-thurow</groupId>
    <artifactId>q2o</artifactId>
    <version>3.16</version>
</dependency>

or download from here.

Versions

Version
3.8