Menu

HibernateD

Vadim Lopatin

HibernateD ORM

NOTE: Project has been divided into 2 subprojects (DDBC and HibernateD) and moved to GitHub!
https://github.com/buggins/ddbc
https://github.com/buggins/hibernated

HibernateD is ORM (Object/Relation Mapping) library for D language with interface and annotations similar to Hibernate ORM for Java.

Contains [DDBC] - D DataBase Connector - similar to JDBC (currently has MySQL and SQLite drivers) - which is used as DB abstraction layer.

Current status

You can annotate your classes with Hibernate-like [Annotations], to add persistance.
Hibernated [Session] allows to save, update, delete, load objects from DB, query DB using [HQL] (Hibernate Query Language).

Simple properties of supported: you can annotate fields, D properties or getter+setter pairs in your class, of types string, byte, short, int, long, ubyte, ushort, uint, ulong, byte[], ubyte[], DateTime, Date, TimeOfDay; for non-nullable types to support Null value use Nullable! template.

@Embedded entities supported - you can embed properties from @Embeddable object to @Entity's table.

@OneToOne, @OneToMany, @ManyToOne, @ManyToMany relations are supported. You can use Lazy! and LazyCollection! to support lazy loading of aggregates.

Sample code

    import ddbc.drivers.mysqlddbc;
    import hibernated.core;
    import hibernated.dialects.mysqldialect;

    // 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;
    }

    // setup DB connection
    MySQLDriver driver = new MySQLDriver();
    string url = MySQLDriver.generateUrl(MYSQL_UNITTEST_HOST, MYSQL_UNITTEST_PORT, MYSQL_UNITTEST_DB);
    string[string] params = MySQLDriver.setUserAndPassword(MYSQL_UNITTEST_USER, MYSQL_UNITTEST_PASSWORD);
    DataSource ds = ConnectionPoolDataSourceImpl(driver, url, params);

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

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

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

    // use session to access DB

    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";
    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.get().remove(0);
    sess.update(u11);

    // remove entity
    sess.remove(u11);

Latest changes

Added DB tables and indexes generation.
Added DDBC SQLite driver.

TODO

  • add cascading for persistence operations
  • add transactions support
  • add PostgeSQL support

Related

Wiki: Annotations
Wiki: DDBC
Wiki: HQL
Wiki: Query
Wiki: Session