1 /* 2 * Entity - Entity is an object-relational mapping tool for the D programming language. Referring to the design idea of JPA. 3 * 4 * Copyright (C) 2015-2018 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: HuntLabs.cn 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.entity.EntityManager; 13 14 import hunt.entity; 15 import hunt.entity.dialect; 16 import hunt.entity.EntityOption; 17 import hunt.entity.eql; 18 import hunt.logging; 19 import hunt.util.Common; 20 21 import std.array; 22 import std.traits; 23 24 /** 25 * 26 */ 27 class EntityManager : Closeable { 28 29 Dialect _dialect; 30 EntityOption _option; 31 Database _db; 32 string _name; 33 private CriteriaBuilder _criteriaBuilder; 34 private EntityTransaction _transaction; 35 private EntitySession _entitySession; 36 37 this(CriteriaBuilder criteriaBuilder, string name, EntityOption option, 38 Database db, Dialect dialect) { 39 assert(db !is null, "The database can't be null"); 40 _criteriaBuilder = criteriaBuilder; 41 _name = name; 42 _option = option; 43 _db = db; 44 _dialect = dialect; 45 // _entitySession = new EntitySession(db); 46 } 47 48 ~this() { 49 // version(HUNT_ENTITY_DEBUG) infof("Closing EntityManager in ~this()"); // bug 50 // close(); 51 } 52 53 T persist(T)(ref T entity) { 54 QueryBuilder builder = _db.createQueryBuilder(); // _factory.createQueryBuilder(); 55 EntityInfo!T info = new EntityInfo!(T)(this, entity); 56 builder.insert(info.getTableName()).values(info.getInsertString()); 57 58 string autoIncrementKey = info.getAutoIncrementKey(); 59 if (!autoIncrementKey.empty()) 60 builder.setAutoIncrease(autoIncrementKey); 61 Statement stmt = getSession().prepare(builder.toString); 62 int r = stmt.execute(autoIncrementKey); 63 64 version (HUNT_ENTITY_DEBUG) { 65 infof("affected: %d, autoIncrementKey: %s, lastInsertId: %d", r, 66 autoIncrementKey, stmt.lastInsertId()); 67 } 68 69 info.setIncreaseKey(entity, stmt.lastInsertId); 70 return entity; 71 } 72 73 T find(T, P)(P primaryKeyOrT) { 74 CriteriaBuilder criteriaBuilder = getCriteriaBuilder(); 75 CriteriaQuery!T criteriaQuery = criteriaBuilder.createQuery!(T); 76 Root!T r; 77 Predicate condition; 78 static if (is(P == T)) { 79 r = criteriaQuery.from(primaryKeyOrT); 80 condition = criteriaBuilder.equal(r.getPrimaryField()); 81 } else { 82 r = criteriaQuery.from(); 83 condition = criteriaBuilder.equal(r.getPrimaryField(), primaryKeyOrT); 84 } 85 TypedQuery!T query = createQuery(criteriaQuery.select(r).where(condition)); 86 return cast(T)(query.getSingleResult()); 87 } 88 89 int remove(T, P)(P primaryKeyOrT) { 90 CriteriaBuilder criteriaBuilder = getCriteriaBuilder(); 91 CriteriaDelete!T criteriaDelete = criteriaBuilder.createCriteriaDelete!(T); 92 Root!T r; 93 Predicate condition; 94 static if (is(P == T)) { 95 r = criteriaDelete.from(primaryKeyOrT); 96 condition = criteriaBuilder.equal(r.getPrimaryField()); 97 } else { 98 r = criteriaDelete.from(); 99 condition = criteriaBuilder.equal(r.getPrimaryField(), primaryKeyOrT); 100 } 101 return createQuery(criteriaDelete.where(condition)).executeUpdate(); 102 } 103 104 int merge(T)(T entity) { 105 CriteriaBuilder criteriaBuilder = getCriteriaBuilder(); 106 CriteriaUpdate!T criteriaUpdate = criteriaBuilder.createCriteriaUpdate!(T); 107 Root!T r = criteriaUpdate.from(entity); 108 Predicate condition = criteriaBuilder.equal(r.getPrimaryField()); 109 110 string primaryKey = r.getEntityInfo().getPrimaryKeyString(); 111 112 EntityFieldInfo[string] fields = r.getEntityInfo().getFields(); 113 114 foreach (string k, EntityFieldInfo v; fields) { 115 string columnName = v.getColumnName(); 116 117 version (HUNT_ENTITY_DEBUG) 118 tracef("Field: %s, Column: %s", k, columnName); 119 if (columnName == primaryKey || columnName.empty()) { 120 version (HUNT_ENTITY_DEBUG) 121 warningf("primaryKey skipped, Field: %s, Column: %s", k, columnName); 122 continue; 123 } 124 125 criteriaUpdate.set(v); 126 } 127 return createQuery(criteriaUpdate.where(condition)).executeUpdate(); 128 } 129 130 void flush() { 131 //TODO 132 } 133 134 EqlQuery!(T) createQuery(T...)(string eql) { 135 return new EqlQuery!(T)(eql, this); 136 } 137 138 EqlQuery!(T) createQuery(T...)(string query_eql, Pageable page) { 139 return new EqlQuery!(T)(query_eql, page, this); 140 } 141 142 TypedQuery!(T, F) createQuery(T, F)(CriteriaQuery!(T, F) query) { 143 return new TypedQuery!(T, F)(query, this); 144 } 145 146 Query!(T) createQuery(T)(CriteriaDelete!T query) { 147 return new Query!(T)(query, this); 148 } 149 150 Query!(T) createQuery(T)(CriteriaUpdate!T query) { 151 return new Query!(T)(query, this); 152 } 153 154 NativeQuery createNativeQuery(string sql) { 155 return new NativeQuery(this, sql); 156 } 157 158 Dialect getDialect() { 159 return _dialect; 160 } 161 162 EntitySession getSession() { 163 if (_entitySession is null) { 164 version (HUNT_DEBUG) { 165 info("Creating a new session"); 166 } 167 _entitySession = new EntitySession(_db); 168 } 169 return _entitySession; 170 } 171 172 CriteriaBuilder getCriteriaBuilder() { 173 return _criteriaBuilder.setManager(this); 174 } 175 176 EntityTransaction getTransaction() { 177 if(_transaction is null) { 178 _transaction = new EntityTransaction(getSession()); 179 } 180 return _transaction; 181 } 182 183 deprecated("Using getSession instead.") Database getDatabase() { 184 return _db; 185 } 186 187 string getDbPoolInfo() { 188 return _db.poolInfo(); 189 } 190 191 DatabaseOption getDbOption() { 192 return _db.getOption(); 193 } 194 195 string getPrefix() { 196 return _option.database.prefix; 197 } 198 199 void close() { 200 if (_entitySession) { 201 _entitySession.close(); 202 } 203 } 204 }