Giter Club home page Giter Club 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

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

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hibernated's Issues

Tables is not created automatically

class Card
{
import hibernated.core;

@Id
@Generated
long id;
@UniqueKey
string pwd;

}

MySQLDriver driver = new MySQLDriver();
string url = MySQLDriver.generateUrl("10.211.55.10", 3306, "test");
string[string] params = MySQLDriver.setUserAndPassword("root", "xxx");
auto ds = new ConnectionPoolDataSourceImpl(driver, url, params);

EntityMetaData schema = new SchemaInfoImpl!(Card); 
Dialect dialect = new MySQLDialect();
auto factory = new SessionFactoryImpl(schema, dialect, ds);


Card c = new Card;
auto s = factory.openSession();
scope(exit) s.close();
s.save(c);

my dub.json

{
"name": "ezsockacount",
"description": "A simple vibe.d server application.",
"copyright": "Copyright © 2015, zhmt",
"authors": ["zhmt"],
"dependencies": {
"vibe-d": ">=0.7.22",
"mysql-native": "0.1.0",
"hibernated": "0.2.19",
"ddbc": ">=0.2.16"
},
"subConfigurations": {
"hibernated": "MySQL",
"ddbc": "MySQL"
},
"versions": ["VibeDefaultMain","USE_MYSQL"]
}

It compiles well, but throw an exception while running:
hibernated.type.MappingException@../../../zhmt/.dub/packages/hibernated-0.2.19/source/hibernated/metadata.d(3332): Cannot find entity by class app.Card

Can you help me?

Sourceforge vs GitHub confusion

This project seems to exist on both Sourceforge and GitHub, and neither one seems to make any mention of the other.

The project pages on both sites should probably be updated to clarify which one is the main, official one, and which one is deprecated - or otherwise clarify what the difference is and which one people should be using.

How can I update changed members in entity class object?

In hibernate,update object is set all table columns to sql.
code for example:

//orm entity
class User {
	int id;
	string firstName;
	string lastName;

    }
Session sess = factory.openSession();
User user =sess.createQuery("FROM User WHERE first_name=:firstName").setParameter("firstName","balabala").uniqueResult!User();

user.lastName = "new balabala";//change last name

sess.update(user);

when exec update method ,hibernate generate sql like that

UPDATE user SET first_name =?, last_name =? WHERE id=?

but i just want to modify or update last_name column, maybe sql is

UPDATE user SET  last_name =? WHERE id=?

does hibernate has a method to update changed columns only?

how can i do that?

problem getting @ManyToOne working

the following seems to break:

@Entity
@Table("books")
public class Book {
    public:
        @Id
        @Generated
        Uint id;

        @Column("title", 250) @NotNull
        string title;

        @ManyToOne @JoinColumn("author_id") @NotNull
        Person author;
}

@Entity
@Table("people")
public class Person {
    public:
        @Id
        @Generated
        Uint id;

        @Column("name", 50) @NotNull
        string name;
}

when I try to get books by user the program bombs out:

Query q = session
        .createQuery("FROM Book WHERE author=:person")
        .setParameter("person", somePersonObject);
return q.list!Book();

v0.2.33 is broken

I am using:

DMD64 D Compiler v2.072.0
DUB version 1.0.0, built on Oct 31 2016

.dub/packages/hibernated-0.2.33/hibernated/source/hibernated/core.d(29,15): Error: module ddbc is in file 'ddbc.d' which cannot be read

Please ensure travis builds are ok before doing a release. Version 0.2.29 was the last version on dub repo that's usable (along with ddbc 0.2.29).

See travis build history logs:

source/htestmain.d(52,22): Error: undefined identifier 'SQLITEDriver'

can't compile.

All the dialect classes override the quotes but they need to have "const" after the function parameters.

Compilation error after upgrade mysql-native to 1.0.0

mysql-native 1.0.0: target for configuration "library" is up to date. ddbc 0.3.2: building configuration "full"... ../../../.dub/packages/ddbc-0.3.2/ddbc/source/ddbc/drivers/mysqlddbc.d(319,15): Error: undefined identifier 'Command' ../../../.dub/packages/ddbc-0.3.2/ddbc/source/ddbc/drivers/mysqlddbc.d(342,23): Error: undefined identifier 'FieldDescription' ../../../.dub/packages/ddbc-0.3.2/ddbc/source/ddbc/drivers/mysqlddbc.d(359,23): Error: undefined identifier 'ParamDescription' dmd failed with exit code 1.

use the newer alias syntax

Since dmd 2.061 the syntax for alias has been updated. We should updated the project to use the newer syntax

hibernated.session.Session conflicts with vibe.http.session.Session

Both define a class Session, which results in the conflict.

Full error description:
source/app.d(8): Error: vibe.http.session.Session at ../../.dub/packages/vibe-d-0.7.17/source/vibe/http/session.d(22) conflicts with hibernated.session.Session at ../../.dub/packages/hibernated-0.2.11/source/hibernated/session.d(48)

Is it possible to execute mysql functions using hql?

i tried to execute CURRENT_DATE(), and UPPER() but i get errors:

"Alias name identifier expected in FROM clause near ...."
"No property CURRENT_DATE found in entity ...."

here is the code i tried;

  1. string cmdtext = format(
    "FROM searchquerymodules AS sqm\r\n" ~
    "JOIN sqm.searchquery AS sq\r\n" ~
    "JOIN sqm._module AS m\r\n" ~
    "WHERE (m.active = 1) and (m.id = %d)" ~
    " and ((sq.expirydate is null) or (sq.expirydate > CURRENT_DATE()))",
    moduleid);
Query q = session.createQuery(cmdtext);

return q.list!searchquerymodules();
  1. string cmdtext = format(
    "FROM notifications n\r\n" ~
    "JOIN n.searchquerymodule as sqm\r\n" ~
    "JOIN sqm.searchquery as sq\r\n" ~
    "WHERE sq.account_id = %d \r\n" ~
    " and sqm.module_id = %d \r\n" ~
    " and UPPER(n.url) = '%s' \r\n" ~
    "", accountid, moduleid, toUpper(url));
   Query q = session.createQuery(cmdtext);
return q.list!notifications();

Missing WHERE clause arguments with @ManyToMany

My sample code below creates an object and saves it correctly to the database, but then fails to load the same object from the database and gives an SQL syntax error as the HQL is missing the arguments to the WHERE clause:

ddbc.core.SQLException@../../.dub/packages/ddbc-0.3.2/ddbc/source/ddbc/drivers/mysqlddbc.d(252): MySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 while execution of query SELECT _t1.id, _t1.name FROM role AS _t1 WHERE

import std.stdio;
import hibernated.core;

class User {
    long id;
    string name;

    @ManyToMany
    Role[] roles;
}

class Role {
    long id;
    string name;

    @ManyToMany
    User[] users;
}


int main(string[] argv)
{
    EntityMetaData schema = new SchemaInfoImpl!(User, Role);

    // setup DB connection factory
    version (USE_MYSQL) {
        MySQLDriver driver = new MySQLDriver();
        string url = MySQLDriver.generateUrl("localhost", 3306, "test");
        string[string] params = MySQLDriver.setUserAndPassword("root", "");
        Dialect dialect = new MySQLDialect();
    } else {
        SQLITEDriver driver = new SQLITEDriver();
        string url = "test.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();

    Role admin = new Role();
    admin.name = "Admin";
    sess.save(admin);

    Role engineer = new Role();
    engineer.name = "Engineer";
    sess.save(engineer);

    Role unix = new Role();
    unix.name = "Unix";
    sess.save(unix);

    User john = new User();
    john.name = "John";
    john.roles = [admin,unix];
    sess.save(john);

    writeln(john.name ~ ":");
    foreach (role; john.roles) {
        writeln(role.name);
    }

    User user = new User();
    sess.load(user, 1);

    return 0;
}

Output:

Performing "debug" build using dmd for x86.
derelict-util 2.0.6: target for configuration "library" is up to date.
derelict-pq 2.0.3: target for configuration "library" is up to date.
mysql-native 0.1.6: target for configuration "library" is up to date.
ddbc 0.3.2: target for configuration "full" is up to date.
hibernated 0.2.32: target for configuration "full" is up to date.
hiberbug ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
Running ./hiberbug
John:
Admin
Unix
ddbc.core.SQLException@../../.dub/packages/ddbc-0.3.2/ddbc/source/ddbc/drivers/mysqlddbc.d(252): MySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 while execution of query SELECT _t1.id, _t1.name FROM role AS _t1 WHERE
----------------
../../.dub/packages/ddbc-0.3.2/ddbc/source/ddbc/drivers/mysqlddbc.d:252 ddbc.core.PreparedStatement ddbc.drivers.mysqlddbc.MySQLConnection.prepareStatement(immutable(char)[]) [0x8196884]
../../.dub/packages/ddbc-0.3.2/ddbc/source/ddbc/common.d:96 ddbc.core.PreparedStatement ddbc.common.ConnectionWrapper.prepareStatement(immutable(char)[]) [0x8192f05]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:1066 Object[] hibernated.session.QueryImpl.listObjects(Object, hibernated.session.PropertyLoadMap) [0x8183838]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:1010 void hibernated.session.QueryImpl.delayedLoadRelations(hibernated.session.PropertyLoadMap) [0x81833b4]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:1083 Object[] hibernated.session.QueryImpl.listObjects(Object, hibernated.session.PropertyLoadMap) [0x8183963]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:1051 Object[] hibernated.session.QueryImpl.listObjects(Object) [0x8183761]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:844 Object hibernated.session.QueryImpl.uniqueObject(Object) [0x81822c5]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:142 Object hibernated.session.Query.uniqueResult!(Object).uniqueResult(Object) [0x818418a]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:397 Object hibernated.session.SessionImpl.getObject(const(hibernated.metadata.EntityInfo), Object, std.variant.VariantN!(24u).VariantN) [0x817f24d]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:390 void hibernated.session.SessionImpl.loadObject(Object, std.variant.VariantN!(24u).VariantN) [0x817f045]
../../.dub/packages/hibernated-0.2.32/hibernated/source/hibernated/session.d:92 void hibernated.session.Session.load!(app.User, int).load(app.User, int) [0x8173880]
source/app.d:86 _Dmain [0x8154138]
??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [0x81e61aa]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x81e60fc]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x81e6166]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x81e60fc]
??:? _d_run_main [0x81e608e]
??:? main [0x8175933]
??:? __libc_start_main [0xb73d772d]
Program exited with code 1

Database contents:

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| role           |
| role_users     |
| user           |
+----------------+
3 rows in set (0.01 sec)

mysql> select * from role;
+----+----------+
| id | name     |
+----+----------+
|  1 | Admin    |
|  2 | Engineer |
|  3 | Unix     |
+----+----------+
3 rows in set (0.01 sec)

mysql> select * from user;
+----+------+
| id | name |
+----+------+
|  1 | John |
+----+------+
1 row in set (0.00 sec)

mysql> select * from role_users;
+---------+---------+
| role_fk | user_fk |
+---------+---------+
|       1 |       1 |
|       3 |       1 |
+---------+---------+
2 rows in set (0.00 sec)

Fails with MappingException in a multithreaded environment

Hi!
When using Hibernated in an environment with multiple threads, occasionally the following error is raised:
hibernated.type.MappingException@/hibernated/hibernated/metadata.d(3375): Cannot find entity by name MyEntity
(with MyEntity being whatever entity I want to deal with at that time).

From looking at the code, this should actually work in a multithreaded environment, so I don't really know what the problem is at time.

Deprecation: std.exception.enforceEx

Deprecation warning when building with 'DMD64 D Compiler v2.082.0'

../../source/hibernated/metadata.d(307,35): Deprecation: function std.exception.enforceEx!(MappingException).enforceEx!bool.enforceExis deprecated - Use enforce. enforceEx will be removed with 2.089. ../../source/hibernated/query.d(93,38): Deprecation: functionstd.exception.enforceEx!(HibernatedException).enforceEx!bool.enforceExis deprecated - Use enforce. enforceEx will be removed with 2.089. ../../source/hibernated/session.d(218,33): Deprecation: functionstd.exception.enforceEx!(CacheException).enforceEx!bool.enforceExis deprecated - Use enforce. enforceEx will be removed with 2.089. ddbctest ~master: building configuration "default"... ../../source/hibernated/metadata.d-mixin-3358(4064,43): Deprecation: functionstd.exception.enforceEx!(MappingException).enforceEx!bool.enforceEx is deprecated - Use enforce. enforceEx will be removed with 2.089.

Can't compile unittests

Using DMD 2.062:

>git clone https://github.com/buggins/hibernated.git
>git clone https://github.com/buggins/ddbc.git
>type blank.d
import hibernated.core;
void main() {}

>rdmd --force -unittest -version=USE_MYSQL -Ihibernated/source -Iddbc/source blank.d

OPTLINK (R) for Win32  Release 8.00.12
Copyright (C) Digital Mars 1989-2010  All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests8Customer7__ClassZ
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests4Role7__ClassZ
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests7Address7__ClassZ
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests11AccountType7__ClassZ
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests4User7__ClassZ
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests8MoreInfo7__ClassZ
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests6Person7__ClassZ
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests12EvenMoreInfo7__ClassZ
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type45__T14LazyCollectionTC€Œ¨5Ùsts4UserZ€�ª8opAssignMFA€™µ€™š
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type45__T14LazyCollectionTC10hibernated5tests4UserZ14LazyCollection3getMFNcZAC10hibernated5tests4User
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type45__T14LazyCollectionTC10hibernated5tests4UserZ14LazyCollection6loadedMFNdZb
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type45__T14LazyCollectionTC10hibernated5tests4UserZ14LazyCollection8opAssignMFDFZAC6ObjectZv
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type45__T14LazyCollectionTC10hibernated5tests4RoleZ14LazyCollection3getMFNcZAC10hibernated5tests4Role
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type45__T14LazyCollectionTC€Œ¨5Ùsts4RoleZ€�ª8opAssignMFA€™µ€™š
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type45__T14LazyCollectionTC10hibernated5tests4RoleZ14LazyCollection6loadedMFNdZb
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type45__T14LazyCollectionTC10hibernated5tests4RoleZ14LazyCollection8opAssignMFDFZAC6ObjectZv
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type42__T4LazyTC10hibernated5tests11AccountTypeZ4Lazy8opAssignMFDFZC6ObjectZv
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type42__T4LazyTC€Œ�5Ùsts11AccountT€ƒ«Z€…§8opAssignMF€¡±€ ¡
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type42__T4LazyTC10hibernated5tests11AccountTypeZ4Lazy6opCallMFZC10hibernated5tests11AccountType
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated4type42__T4LazyTC10hibernated5tests11AccountTypeZ4Lazy6loadedMFNdZb
C:\Users\Nick\AppData\Local\Temp\.rdmd\rdmd-blank.d-F116464A3D0082C5B1262C0BD2C12CFD\objs\blank.obj(blank) 
 Error 42: Symbol Undefined _D10hibernated5tests12__ModuleInfoZ
--- errorlevel 21

What type is ID in `T get(T : Object, ID)(ID id)`

What type is ID ? I am not able to find any thing called ID in HibernateD source code. It fails if I pass in an integer.

T get(T : Object, ID)(ID id) 
T load(T : Object, ID)(ID id) 
void load(T : Object, ID)(T obj, ID id)

add support for @Inheritance

Hibernate allows support for inheritance making it possible to things like this:

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="content_type", discriminatorType=DiscriminatorType.STRING)
@Table("site_content")
public class SiteContent {
    @Id
    @Generated
    public uint id;

    @Column("title") @NotNull
    public string title;

    @Column("content") @NotNull
    public string content; // LONGTEXT
}

@Entity
@DiscriminatorValue("wikipage")
public class WikiPage : SiteContent {}

@Entity
@DiscriminatorValue("blogpost")
public class BlogPost : SiteContent {}

More information on @Inheritance and the related annotations can be found here.

@Embedded class fields are considered NotNull

class Customer {
    int id;
    string name;
    // Embedded is inferred from type of Address
    Address address;
    this() {
        address = new Address();
    }
}

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

If zip is not set, it's impossible to save object
Customer c10 = new Customer();
c10.name = "Customer 10";
sess.save(c10);
Fails on NotNull check for address.zip

Can't compile (unreachable return statement)

I get this compilation error:

../../.dub/packages/hibernated-0.2.11/source/hibernated/dialects/pgsqldialect.d(197): Warning: statement is not reachable

Perhaps a case statement is missing or one of the two returns should be commented out?

Exception: Invalid quoted identifier near _id

Although i was trying something a bit complex here,
I think the parser doesn't like tables or column names with an underscore in it.

2013-May-31 20:51:48.6802862 - Exception: Invalid quoted identifier near _id
INNER JOIN modules on modules.id = searchquerymodules.module_id
WHERE (modules.id = 2) and (modules.active = 1) and ((searchqueries.expirydate is null) or (searchqueries.expirydate > CURDATE()))

Crash with ldc2 1.1.0-beta2 on querying list of objects

Using SQLite3 as backend, and ldc2 as compiler, leads to a crash. Adding an entry works, but retrieving a list of objects causes the test to crash (testcase attached).

hibernated_test.zip

Output from gdb:

(gdb) where
#0  0x000000000042980f in hibernated.metadata.SchemaInfoImpl!(hibernated_test.Entry).SchemaInfoImpl.findEntityForObject(Object) const ()
#1  0x000000000044fbe2 in hibernated.metadata.SchemaInfo.readAllColumns(Object, ddbc.core.DataSetReader, int) const ()
#2  0x0000000000475273 in hibernated.session.QueryImpl.readRelations(Object, ddbc.core.DataSetReader, hibernated.session.PropertyLoadMap) ()
#3  0x0000000000477ac9 in hibernated.session.QueryImpl.listObjects(Object, hibernated.session.PropertyLoadMap) ()
#4  0x0000000000474490 in hibernated.session.QueryImpl.listObjects(Object) ()
#5  0x00000000004764a6 in hibernated.session.QueryImpl.listObjects() ()
#6  0x00000000004224e2 in hibernated.session.Query.list!(hibernated_test.Entry).list() ()
#7  0x0000000000422180 in D main ()

update table columns with updateDBSchema if required

It would be nice if updateDBSchema also added/removed table columns when fields are added and removed from the respective class. I suspect this is one of those features that sounds easy but has a lot of edge cases to be handled?

Conversation I had in IRC #D relevent to hibernated

FYI: According to this conversation using static if is causing warnings on some systems. more info here: techwulf/testhibernated#1

Let me know if I can help.

<Master_Foo> Hey everyone. I'm trying to help techwulf with an issue and it's beyond my knowledge.
<Master_Foo> Basically, if he compiles a program and he gets warnings the whole build fails.
<Master_Foo> But I don't get those same warnings
<Master_Foo> more info here: https://github.com/techwulf/testhibernated/issues/1
<alphaglosined> dmd has an argument which makes warnings errors
<Master_Foo> Help is apreciated
<Master_Foo> Is that a setting or something?
<adam_d_ruppe> -wi
<alphaglosined> its -w
<alphaglosined> -wi is warning as message
<alphaglosined> -wi should be the default
<adam_d_ruppe> dub sets the warning as error setting though
<Master_Foo> So, if we are compiling from the same code base, with the same dub file. And mine compiles without error, but he gets errors, what is up with that?
<adam_d_ruppe> it is prolly a platform thing
<adam_d_ruppe> can you check the file and line it references
<adam_d_ruppe> ../../.dub/packages/hibernated-0.2.26/source/hibernated/metadata.d(617,5):
<adam_d_ruppe> and that , hmm
<alphaglosined> if you are getting statement cannot be reached, that to me is an error
<Master_Foo> I checked that file. The code seems OK (It compiles on my machine)
<adam_d_ruppe> check the line though to see if it is in a version block
<Master_Foo> OK, brb...
<adam_d_ruppe> his build is 64 it, yours might be 32
<adam_d_ruppe> or maybe he is on mac and you are on linux
<adam_d_ruppe> something like that
<techwulf> I'm using arch linux
<Master_Foo> We are using the same build. But he is arch and I am mint
<alphaglosined> yeah, that static if needs to be an if
<adam_d_ruppe> all the same source too?
<alphaglosined> https://github.com/buggins/hibernated/blob/master/source/hibernated/metadata.d#L613
<adam_d_ruppe> idk i'm blindly guessing
<Master_Foo> I just checked the library. It is not in a version block
* dewitt ([email protected]) has joined
<alphaglosined> static if is like version here, causes problems
<alphaglosined> an if statement will work just as well and won't cause the error like static if does
<alphaglosined> by the looks of things, this style with the static if is used everywhere
<alphaglosined> which is a problem
<Master_Foo> I understand, but I really can't change buggins code base. It's not my library. Maybe I'll help him on it if he is interested, but for now is there a work around?
<alphaglosined> nope, do a PR
<Master_Foo> PR?
<alphaglosined> don't ask just do
<alphaglosined> pull request
* dewitt has quit (Client Quit)
<alphaglosined> with the help of add-local from dub you will be able to test this for your use case
<Master_Foo> for now, can we figure out why it specifically works on my machine but not techwulf's?
<alphaglosined> check your sc.ini file
<alphaglosined> well techwulf should
<alphaglosined> more than likely -w is being passed in there
<Master_Foo> What specifically are we looking for?
* eletuchy has quit (Remote host closed the connection)
<Master_Foo> OK, cool.
<Master_Foo> Thank's for the help!
<alphaglosined> what version of dub are you both using?
<Master_Foo> just a sec...
* johndau` ([email protected]) has joined
<Master_Foo> DUB version 0.9.24+31-ga814c0c, built on Sep 22 2015
<Master_Foo> techwulf do a dub --version
<techwulf> 0.0.24
<techwulf> 0.9.24
<alphaglosined> ok so recent, I just want to be sure you weren't mis matching
<Master_Foo> OK we are both on the same page there.
<Master_Foo> We'll go compare our sc.ini files. I'm sure that is the issue.
<Master_Foo> thanks!
<alphaglosined> I'm not, just to eliminate -w isn't being added there
<alphaglosined> ok one thing, silenceWarnings != allowWarnings
* johndau has quit (Ping timeout: 246 seconds)
<alphaglosined> you want allowWarnings
<alphaglosined> for your buildRequirements
<alphaglosined> silenceWarnings will shut dmd up and not display it
<Master_Foo> Yeah, I told him to silecneWarnings because that was preventing him from compiling.
<Master_Foo> We'll try allowWarnings
<Master_Foo> That might be better than changing the sc.ini file. Right? Keeps everyone on the project on the same page without having to modify the ini file?
<Master_Foo> Forgive my ignorance.
<alphaglosined> sc.ini will either have -w in it or not
<alphaglosined> if it does, something went wrong on the install and I have no idea why its there
* johndau` has quit (Quit: ERC (IRC client for Emacs 24.5.1))
<alphaglosined> its a simple grep to determine if its there, no biggy
* johndau ([email protected]) has joined
<techwulf> Thankyou everyone for the help.
<techwulf> *thank you
<Master_Foo> Problem solved, thanks alphaglosined and adam_d_ruppe
<alphaglosined> No problem!

update travis build to use multiple compilers

The current travis build is using legacy system and only attempts to compile with dmd:

language: d
script: dub test --config=SQLite

It would be handy to see if it will build under various configurations. Something like the following:

language: d

sudo: false

d:
  - dmd-2.069.2
  - dmd-2.068.2
  - dmd-2.067.1
  - dmd-2.066.1
  - ldc-0.16.1
  - ldc-0.15.1
  - gdc-5.2.0
  - gdc-4.9.2

os:
 - linux
 - osx

script: dub test --config=SQLite

Licensing

Hi,

I'm interested in using HibernateD and DDBC for a project, but I can't seem to find a license anywhere. Is this available anywhere?

Compilation error: undefined identifier app.User

Hi,

I could not build a simple project using sqlite3 on Windows.
Please find 2 files of the project listed below.

Compilation errors look as follows.

C:\Sandbox\GitHub\hibernated\source\hibernated\metadata.d(3213): Error: undefined identifier app.User
C:\Sandbox\GitHub\hibernated\source\hibernated\metadata.d(3213): Error: undefined identifier app.User
C:\Sandbox\GitHub\hibernated\source\hibernated\metadata.d(3218): Error: undefined identifier app.User
C:\Sandbox\GitHub\hibernated\source\hibernated\metadata.d(3218): Error: undefined identifier app.User
C:\Sandbox\GitHub\hibernated\source\hibernated\metadata.d(3223): Error: undefined identifier app.User
C:\Sandbox\GitHub\hibernated\source\hibernated\metadata.d(3223): Error: undefined identifier app.User
...

1. package.json

{
    "name": "zzz",
    "description": "An example project skeleton",
    "homepage": "http://example.org",
    "copyright": "Copyright © 2000, Your Name",
    "authors": [
        "Your Name"
    ],
    "dependencies": {
        "ddbc": {"version": "0.2.6", "path": "../../GitHub/ddbc"},
        "hibernated": {"version": "0.2.8", "path": "../../GitHub/hibernated"}
    },
    "subConfigurations": {
        "ddbc": "SQLite",
        "hibernated": "SQLite"
    },
    "targetPath": "bin"
}

2. source/app.d

import ddbc.drivers.sqliteddbc;
import hibernated.core;
import hibernated.dialects.sqlitedialect;

// Annotations of entity classes
class User {
    long id;
    string name;
    @ManyToMany // cannot be inferred, requires annotation
    LazyCollection!Role roles;
}

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

void main()
{
    // setup DB connection
    SQLITEDriver driver = new SQLITEDriver();
    string[string] params;
    DataSource ds = new ConnectionPoolDataSourceImpl(driver, "zzz.db", params);

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

    // create session factory
    Dialect dialect = new SQLiteDialect();
    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";
    User u10 = new User();
    u10.name = "Alex";
    u10.roles = [r10, r11];
    sess.save(r10);
    sess.save(r11);
    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.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);
}

explicitely commit?

Currently trying to populate a sqlite database, I just read a very large file line by line, create one object from each line then sess.save(myObject)

It then eats up all my memory and fail... Is there a way to explicitely commit (like sess.commit()) ?

add support for unique constraint

The @Column definition currently:

struct Column {
    immutable string name;
    immutable int length;
}

It would be great if there was a third parameter to mark a column as being unique:

struct Column {
    immutable string name;
    immutable int length;
    immutable bool unique;
}

hibernated 0.2.11 and ~master can not be used with vibe-d

hibernated 0.2.11 and ~master depend on ddbc 0.2.9, which depends on mysql-nativ 0.0.9. mysql-nativ 0.0.9 can not be used with the current vibe.d release.

Compile error output
../../.dub/packages/mysql-native-0.0.9/source/mysql/connection.d(255): Error: no property 'acquire' for type 'vibe.core.net.TCPConnection'
../../.dub/packages/mysql-native-0.0.9/source/mysql/connection.d(256): Error: no property 'release' for type 'vibe.core.net.TCPConnection'
../../.dub/packages/mysql-native-0.0.9/source/mysql/connection.d(257): Error: no property 'isOwner' for type 'vibe.core.net.TCPConnection'
../../.dub/packages/mysql-native-0.0.9/source/mysql/connection.d(258): Error: no property 'isOwner' for type 'vibe.core.net.TCPConnection'

ddbc ~master depends on mysql-nativ 0.0.10, which fixes the issue. hibernated ~master should depend on ddbc ~master, until the future release of ddbc.

Suggested changes
diff --git a/package.json b/package.json
index c61ec62..f4f897d 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
     "homepage": "https://github.com/buggins/hibernated",
     "license": "Boost Software License (BSL 1.0)",
     "dependencies": {
-        "ddbc": ">=0.2.9"
+        "ddbc": "~master"
     },
     "targetType": "staticLibrary",
     "configurations": [

Support for setMaxResults and setFirstResult is missing

Hi!
First of all, thank you for this gem of D code! It has saved me a lot of work already!

To display database content on multiple pages, I need support for Hibernate's setMaxResults and setFirstResult Query methods, but surprisingly those are missing from Hibernated.
(As well as support for COUNT(), but that is less of a problem because raw SQL can replace this).

Would it be possible to add the two methods? Or am I missing something and this kind of feature is already implemented differently?

Serialization of Schema

Hi

I'm writing a framework using HibernateD and I need the SchemaInfo and QueryBuilder for an OData implementation (all controllers of the framework must be OData for extensibility reasons). I would have an object instance with a schema as a member object, which loads and disposes of schemas depending on the hostname of a web request. The reason I need to load and dispose it at runtime is because different libraries may extend the schemas at runtime, and some libraries might not be loaded for a specific hostname.

The solution is to copy this schema for each hostname, and extend some of these copies depending on which libraries will be loaded, but the copying and extending part is mostly runtime (because a configuration file defines the hostnames that will be run).

So the reason I'm asking for help is, there's no way to copy a schema or load it back into a SchemaInfoImpl(T...) object. Since you wrote this library, I'm wondering if you have a quick solution for this.

Thanks

edit: I can settle with Variant on this one if adapting to a serialization library that supports ubyte[] representation is too tough.

example1 fails to compile with:- Error: module std.traits import 'Filter' not found

Running dub in examples/example1 folder gives an error:
../../source/hibernated/metadata.d(841,12): Error: module std.traits import 'Filter' not found

Operating System: osx MacOS Sierra 10.12.6
Using dmd and dub versions:
⋊> ~/.../e/example1 on master ⨯ dub --version
DUB version 1.5.0, built on Sep 1 2017

⋊> ~/.../e/example1 on master ⨯ dmd --version
DMD64 D Compiler v2.076.0

Fixed by changing
source/hibernated/metadata.d line:841
import std.traits : FieldTypeTuple, Filter;
to
import std.traits : FieldTypeTuple;
import std.meta : Filter;

v0.2.32 is broken

hibernated-0.2.32/hibernated/source/hibernated/metadata.d(661,17): Error: enclosing label 'Louter' for break not found

please add support for @Enumerated

I can map an enum from a number but what about mapping an enum from a string? It would be nice to be able to do:

@Enumerated(EnumType.ORDINAL)

or

@Enumerated(EnumType.STRING)

Deprecation in metadata.d caused by Nullable.get

tons of deprecation messages being output. Essentially the problem is Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.

So these will have to be fixed asap.

Example log output:

source/hibernated/metadata.d-mixin-3369(5026,86): Deprecation: function std.typecons.Nullable!(Date).Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5036,68): Deprecation: function std.typecons.Nullable!(Date).Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5036,68): Deprecation: function std.typecons.Nullable!(Date).Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5064,86): Deprecation: function std.typecons.Nullable!(TimeOfDay).Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5074,73): Deprecation: function std.typecons.Nullable!(TimeOfDay).Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5074,73): Deprecation: function std.typecons.Nullable!(TimeOfDay).Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5178,88): Deprecation: function std.typecons.Nullable!float.Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5188,70): Deprecation: function std.typecons.Nullable!float.Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5216,90): Deprecation: function std.typecons.Nullable!double.Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.
source/hibernated/metadata.d-mixin-3369(5226,72): Deprecation: function std.typecons.Nullable!double.Nullable.get_ is deprecated - Implicit conversion with alias Nullable.get this will be removed after 2.096. Please use .get explicitly.

not working with latest dmd (v2.069.2)

I had to updatd my version of dmd due to min requirements of another dependency in my project but unfortunately updating dmd has caused hibernated to stop working. Is there any work on this at the moment?

Range violation when using more than one OneToMany fields

import hibernated.core, hibernated.session;
import ddbc.drivers.sqliteddbc;
import std.algorithm;
import std.stdio;

class ForumUser
{
    @Generated @Id int id;
    Post[] posts; // <--
    IPAddr[] ips; // <--
    string name;
}

class Post
{
    @Generated @Id int id;
    ForumUser user;
}

class IPAddr
{
    @Generated @Id int id;
    ForumUser user;
}

int main()
{
    EntityMetaData schema = new SchemaInfoImpl!(ForumUser, Post, IPAddr);

    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);
    

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

    {
        Connection conn = ds.getConnection();
        scope(exit) conn.close();
        factory.getDBMetaData().updateDBSchema(conn, false, true);
    }

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

    auto u = new ForumUser;
    u.name = "foo";
    sess.save(u);

    ForumUser[] users = sess.createQuery("FROM ForumUser").list!ForumUser;

    return 0;
}

In the above example, commenting out either Post[] posts; or IPAddr[] ips; makes the example compile and run. Otherwise, I get the following:

Running ./multi_fail
core.exception.RangeError@../../.dub/packages/hibernated-0.2.33/hibernated/source/hibernated/session.d(801): Range violation
----------------
??:? _d_arraybounds [0x7a68f3]
??:? hibernated.session.__array [0x68f1b1]
../../.dub/packages/hibernated-0.2.33/hibernated/source/hibernated/session.d:801 hibernated.session.PropertyLoadItem hibernated.session.PropertyLoadMap.remove(const(hibernated.metadata.PropertyInfo)) [0x694890]
../../.dub/packages/hibernated-0.2.33/hibernated/source/hibernated/session.d:973 void hibernated.session.QueryImpl.delayedLoadRelations(hibernated.session.PropertyLoadMap) [0x695c1a]
../../.dub/packages/hibernated-0.2.33/hibernated/source/hibernated/session.d:1083 Object[] hibernated.session.QueryImpl.listObjects(Object, hibernated.session.PropertyLoadMap) [0x696a00]
../../.dub/packages/hibernated-0.2.33/hibernated/source/hibernated/session.d:1050 Object[] hibernated.session.QueryImpl.listObjects(Object) [0x69671b]
../../.dub/packages/hibernated-0.2.33/hibernated/source/hibernated/session.d:964 Object[] hibernated.session.QueryImpl.listObjects() [0x695b6a]
../../.dub/packages/hibernated-0.2.33/hibernated/source/hibernated/session.d:151 app.ForumUser[] hibernated.session.Query.list!(app.ForumUser).list() [0x682e3c]
source/app.d:60 _Dmain [0x6547a8]
??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [0x7acd2e]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x7acc74]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x7accea]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x7acc74]
??:? _d_run_main [0x7acbee]
??:? main [0x684ab1]
??:? __libc_start_main [0x91aef290]
Program exited with code 1

The function delayedLoadRelations (session.d:973) seems suspicious, but as of now I wasn't able to make it work.

hdtest fails when run against MySQL

I'm working on a branch that will run hdtest using mysql but it seems that hibernated will currently end up in a segmentation fault:

Loading User
query result: []
Checking User 11 : null
Segmentation fault (core dumped)

Selection results count does not equal DB rows count

Hello. I'm writting small site based on vibe.d + HibernateD + MySQL as experiment, and I have trouble with results. I do not know why, but if I make model with one set of fields, I get less results than exist in database, and if I remove some fields, I can get all of them. It's strange.

There is my code.

My table (MySQL dump)

CREATE DATABASE  IF NOT EXISTS `mydb` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `mydb`;
-- MySQL dump 10.13  Distrib 5.5.41, for debian-linux-gnu (x86_64)
--
-- Host: 127.0.0.1    Database: mydb
-- ------------------------------------------------------
-- Server version   5.5.41-0ubuntu0.14.04.1

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `user`
--

DROP TABLE IF EXISTS `user`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `password_hash` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `birthdate` date NOT NULL DEFAULT '0000-00-00',
  `role` tinyint(4) NOT NULL DEFAULT '3',
  `sex` tinyint(1) NOT NULL DEFAULT '0',
  `rating` tinyint(4) NOT NULL DEFAULT '0',
  `balance` float NOT NULL DEFAULT '0',
  `city_id` int(11) DEFAULT NULL,
  `country_id` int(11) DEFAULT NULL,
  `photo_id` varchar(255) DEFAULT NULL,
  `ban_id` int(11) DEFAULT NULL,
  `registered_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `last_visit` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `removed_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `rating_quantity` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `user`
--

LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES
(1,'admin','','[email protected]','0000-00-00',4,0,0,0,NULL,NULL,NULL,NULL,'2014-12-01 00:45:46','0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00',0),
(2,'testuser1','','[email protected]','0000-00-00',1,1,8,1000,1,1,NULL,NULL,'2014-12-01 12:08:34','0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00',0),
(3,'test2','','[email protected]','0000-00-00',1,0,4,1000,1,1,NULL,NULL,'2014-12-01 12:08:34','0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00',0),
(4,'test3','','[email protected]','0000-00-00',1,1,4,100,1,1,NULL,NULL,'2014-12-01 12:08:34','0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00',0),
(5,'test4','','[email protected]','0000-00-00',1,1,4,1100,1,1,NULL,NULL,'2014-12-01 12:08:34','0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00',0);
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2015-02-01 16:00:30

Model:

@Entity
@Table("user")
class User
{
    @Id @Generated
    @Column
    string id;

    @Column
    string name;

    @Column("password_hash")
    string passwordHash;

    @Column
    string email;

    @Column
    ubyte role;

    @Column
    ubyte sex;

    @Column
    float rating;

    @Column
    float balance;

    @Column("city_id")
    Nullable!uint cityID;

    @Column("country_id")
    Nullable!uint countryID;

    @Column("photo_id")
    Nullable!string photoID;

    @Column("ban_id")
    Nullable!uint banID;

    @Column("registered_at")
    DateTime registeredAt;

    // There is that strange fields. If I comment it, everything becomes all right

    // First
    @Column("updated_at")
    DateTime updatedAt;

    // Second
    @Column("last_visit")
    DateTime lastVisit;

    // Third
    @Column("removed_at")
    DateTime removedAt;

    // if I remove or change this element's place, with uncommented "strangers"
    // there will be no results from DB
    @Column("rating_quantity")
    string ratingQuantity;
}

HibernateD initialization:

import hibernated.core;
import std.typecons : Nullable;
import std.datetime : DateTime, Date;

static this()
{
    // create metadata from annotations
    EntityMetaData schema = new SchemaInfoImpl!(User);

    // setup DB connection factory
    MySQLDriver driver = new MySQLDriver();
    string url = MySQLDriver.generateUrl("localhost", 3306, "mydb");
    string[string] params = MySQLDriver.setUserAndPassword("root", "");
    DataSource ds = new ConnectionPoolDataSourceImpl(driver, url, params);

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

    // 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");

    foreach( user; q.list!User() )
        writefln( "id: %s, name: %s", user.id, user.name );
}

With fields writefln gets next result:

id: 1, name: admin
id: 4, name: test3
id: 2, name: testuser1

Without:

id: 1, name: admin
id: 3, name: test2
id: 4, name: test3
id: 5, name: test4
id: 2, name: testuser1

SQL produced by system is trivial

SELECT _t1.id, _t1.name, _t1.password_hash, _t1.email, _t1.role, _t1.sex, _t1.rating, _t1.balance, _t1.city_id, _t1.country_id, _t1.ban_id, _t1.registered_at, _t1.updated_at, _t1.last_visit, _t1.removed_at, _t1.rating_quantity FROM user AS _t1 ORDER BY _t1.name

Can you reproduce that? Is it a bug, or I did something wrong?

hibernated 0.2.11 and ~master compile warnings

The following warning is generated, when compiling hibernated.

../../.dub/packages/hibernated-master/source/hibernated/metadata.d(1120): Warning: statement is not reachable

That line can simply be romved to allow the compilation.

Suggested changes
diff --git a/source/hibernated/metadata.d b/source/hibernated/metadata.d
index 8e124dc..5cce6bf 100644
--- a/source/hibernated/metadata.d
+++ b/source/hibernated/metadata.d
@@ -1117,7 +1117,6 @@ bool isMainMemberForProperty(T : Object, string m)() {
             static assert (!thisMemberHasAnnotation || !hasAnnotadedGetter, "Both getter and corresponding field have annotations. Annotate only one of them.");
             return !hasAnnotadedGetter && (thisMemberHasAnnotation || !hasGetter);
         }
-        return false;
     } else {
         // member is not public
         return false;
See also

https://github.com/vakkermans/hibernated/commit/2b5cc1bdec1df91d3fba12663d7e22f0251a0fb6

can't compile examples

i'm trying to run the examples with v2.068 but it fails with:

../../../.dub/packages/hibernated-master/source/hibernated/session.d(142,35): Error: cannot cast expression this.uniqueObject(cast(Object)obj) of type object.Object to typeof(null)
../../../.dub/packages/hibernated-master/source/hibernated/session.d(839,28): Error: template instance hibernated.session.Query.uniqueResult!(typeof(null)) error instantiating

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.