Git Product home page Git Product logo

hibernated's Introduction

HibernateD

DUB Package GitHub CI Gitter

HibernateD is ORM for D language (similar to Hibernate)

The project is hosted on github with documentation available on the wiki.

Uses DDBC as an abstraction layer for the underlying database. DDBC currently supports SQLite, MySQL, Postgres, SQL Server, and potentially Oracle.

SQL dialects supported by Hibernated

Currently hiberanted supports:

  • SQLite (requires SQLite v3.7.11 or later)
  • MySQL (tests are run against mysql v5.7)
  • Postgres

But since the underlying DDBC library now has ODBC support some work is underway to also add

  • SQL Server (2017 & 2019)
  • Oracle (due to the size of the docker image for Oracle this may not be tested during CI)

Sample code:

import hibernated.core;
import std.algorithm;


// Annotations of entity classes

class User {
    long id;
    string name;
    Customer customer;
    @ManyToMany // cannot be inferred, requires annotation
        LazyCollection!Role roles;
}

class Customer {
    int id;
    string name;
    // Embedded is inferred from type of Address
    Address address;

    Lazy!AccountType accountType; // ManyToOne inferred

    User[] users; // OneToMany inferred

    this() {
        address = new Address();
    }
}

@Embeddable
class Address {
    string zip;
    string city;
    string streetAddress;
}

class AccountType {
    int id;
    string name;
}

class Role {
    int id;
    string name;
    @ManyToMany // w/o this annotation will be OneToMany by convention
        LazyCollection!User users;
}

int main() {

    // create metadata from annotations
    EntityMetaData schema = new SchemaInfoImpl!(User, Customer, AccountType, 
            Address, Role);




    // setup DB connection factory
    version (USE_MYSQL) {
        import ddbc.drivers.mysqlddbc;
        MySQLDriver driver = new MySQLDriver();
        string url = MySQLDriver.generateUrl("localhost", 3306, "test_db");
        string[string] params = MySQLDriver.setUserAndPassword("testuser", "testpasswd");
        Dialect dialect = new MySQLDialect();
    } else {
        import ddbc.drivers.sqliteddbc;
        SQLITEDriver driver = new SQLITEDriver();
        string url = "zzz.db"; // file with DB
        static import std.file;
        if (std.file.exists(url))
            std.file.remove(url); // remove old DB file
        string[string] params;
        Dialect dialect = new SQLiteDialect();
    }
    DataSource ds = new ConnectionPoolDataSourceImpl(driver, url, params);


    // create session factory
    SessionFactory factory = new SessionFactoryImpl(schema, dialect, ds);
    scope(exit) factory.close();

    // Create schema if necessary
    {
        // get connection
        Connection conn = ds.getConnection();
        scope(exit) conn.close();
        // create tables if not exist
        factory.getDBMetaData().updateDBSchema(conn, false, true);
    }

    // Now you can use HibernateD

    // create session
    Session sess = factory.openSession();
    scope(exit) sess.close();

    // use session to access DB

    // read all users using query
    Query q = sess.createQuery("FROM User ORDER BY name");
    User[] list = q.list!User();

    // create sample data
    Role r10 = new Role();
    r10.name = "role10";
    Role r11 = new Role();
    r11.name = "role11";
    Customer c10 = new Customer();
    c10.name = "Customer 10";
    c10.address = new Address();
    c10.address.zip = "12345";
    c10.address.city = "New York";
    c10.address.streetAddress = "Baker st., 12";
    User u10 = new User();
    u10.name = "Alex";
    u10.customer = c10;
    u10.roles = [r10, r11];
    sess.save(r10);
    sess.save(r11);
    sess.save(c10);
    sess.save(u10);

    // load and check data
    User u11 = sess.createQuery("FROM User WHERE name=:Name").
        setParameter("Name", "Alex").uniqueResult!User();
    assert(u11.roles.length == 2);
    assert(u11.roles[0].name == "role10" || u11.roles.get()[0].name == "role11");
    assert(u11.roles[1].name == "role10" || u11.roles.get()[1].name == "role11");
    assert(u11.customer.name == "Customer 10");
    assert(u11.customer.users.length == 1);
    assert(u11.customer.users[0] == u10);
    assert(u11.roles[0].users.length == 1);
    assert(u11.roles[0].users[0] == u10);

    // remove reference
    u11.roles = u11.roles().remove(0);
    sess.update(u11);

    // remove entity
    sess.remove(u11);
    return 0;
}

Additional Features

Composite Keys

If a database contains tables with a composite primary key, the @EmbeddedId can be used to represent this. The columns that represent the primary key should be in an @Embeddable class which is then referenced in a property annotated with @EmbeddedId.

For example, consider a database table created via the following SQL command:

CREATE TABLE invoices (
    vendor_no VARCHAR(8) NOT NULL,
    invoice_no VARCHAR(20) NOT NULL,
    amount_e4 INTEGER);
ALTER TABLE invoices
    ADD CONSTRAINT invoices_pkey PRIMARY KEY (vendor_no, invoice_no);

To represent this using HibernateD, the following code would be used:

@Embeddable
class InvoiceId {
    string vendorNo;
    string invoiceNo;

    // Be sure to implement this to benefit from session caching.
    bool opEquals(const InvoiceId o) const @safe {
        return vendorNo == o.vendorNo && invoiceNo == o.invoiceNo;
    }
}

@Table("invoices")
class Invoice {
    @EmbeddedId InvoiceId invoiceId;
    int amountE4;
}

Note: At the time of writing, there are important limitations.

  1. The function DBInfo.updateDbSchema(Connection conn, bool dropTables, bool createTables) does not generate schemas with compound keys.
  2. The Hibernate annotation @JoinColumns (plural) has not yet been implemented, thus, the @ManyToOne and @ManyToMany relations are not usable for classes using an @EmbeddedId.
  3. The @Embedded class referenced via an @EmbeddedId property should implement opEquals in order to gain performance benefits from session caching. These features will be added in future updates.

hibernated's People

Contributors

singingbush avatar buggins avatar arjankn avatar vnayar avatar krzaq avatar theweirddev avatar donglei avatar john-colvin avatar jgoett154 avatar john-remitly avatar lesderid avatar wrzoski avatar gitter-badger avatar gzsombor avatar deviator avatar sinkuu avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.