forked from playframework/play-slick
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DatabaseConfigProvider.scala
200 lines (188 loc) · 7.89 KB
/
DatabaseConfigProvider.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
package play.api.db.slick
import slick.basic.BasicProfile
import slick.basic.DatabaseConfig
/**
* Generic interface for a provider of a `DatabaseConfig` instance. A `DatabaseConfig` is Slick type
* that bundles a database and profile.
*
* Usually, you shouldn't need to create instances of `DatabaseConfigProvider` explicitly. Rather, you
* should rely on dependency injection. If you don't want to use dependency injection, then use the
* companion object and call `DatabaseConfigProvider.get`.
*
* ==Example==
*
* Here is an example of how you can use dependency injection to obtain an instance of `DatabaseConfigProvider`,
* for the database named `default` in your **application.conf**.
* {{{
* class Application @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) {
* // ...
* }
* }}}
*
* While here is an example for injecting a `DatabaseConfigProvider` for a database named `orders` in your
* **application.conf**.
* {{{
* import play.db.NamedDatabase
* class Application @Inject()(@NamedDatabase("orders") protected val dbConfigProvider: DatabaseConfigProvider) {
* // ...
* }
* }}}
*/
trait DatabaseConfigProvider {
def get[P <: BasicProfile]: DatabaseConfig[P]
}
/**
* Look up a `DatabaseConfig` (which is Slick type that bundles a database and profile) for the passed
* database name. The `DatabaseConfig` instance is created using the database's configuration you have
* provided in your **application.conf**, for the passed database name.
*
* Note that if no database name is passed, `default` is used, and hence the configuration
* `slick.dbs.default` is used to create the `DatabaseConfig` instance.
*
* ==Example==
*
* Here is an example for obtaining a `DatabaseConfig` instance for the database named `default` in
* your **application.conf**.
* {{{
* import play.api.Play
* import play.api.db.slick.DatabaseConfigProvider
* import slick.profile.RelationalProfile
* val dbConfig = DatabaseConfigProvider.get[RelationalProfile](Play.current)
* }}}
*
* While here is an example for obtaining a `DatabaseConfig` instance for the database named `orders`
* in your **application.conf**.
* {{{
* import play.api.Play
* import play.api.db.slick.DatabaseConfigProvider
* import slick.profile.RelationalProfile
* val dbConfig = DatabaseConfigProvider.get[RelationalProfile]("orders")(Play.current)
* }}}
*/
object DatabaseConfigProvider {
import play.api.Application
private object DatabaseConfigLocator {
import play.api.Configuration
private val slickApiCache = Application.instanceCache[SlickApi]
private def slickApi(implicit app: Application): SlickApi = slickApiCache(app)
private val configurationCache = Application.instanceCache[Configuration]
private def configuration(implicit app: Application): Configuration = configurationCache(app)
@throws(classOf[IllegalArgumentException])
def apply[P <: BasicProfile](implicit app: Application): DatabaseConfig[P] = {
val defaultDbName = configuration.underlying.getString(SlickModule.DefaultDbName)
this(defaultDbName)
}
@throws(classOf[IllegalArgumentException])
def apply[P <: BasicProfile](dbName: String)(implicit app: Application): DatabaseConfig[P] =
slickApi.dbConfig[P](DbName(dbName))
}
/**
* Returns a Slick database config for the `default` database declared in your **application.conf**.
* Throws a IllegalArgumentException if your **application.conf** does not contain a configuration for
* the `default` database.
*
* @return a Slick `DatabaseConfig` instance for the `default` database.
*/
@throws(classOf[IllegalArgumentException])
@deprecated(
"Use DatabaseConfigProvider#get[P] or SlickApi#dbConfig[P](\"default\") on injected instances",
"3.0.0"
)
def get[P <: BasicProfile](implicit app: Application): DatabaseConfig[P] =
DatabaseConfigLocator(app)
/**
* Returns a Slick database config for the passed `dbName`.
* Throws a IllegalArgumentException if no database configuration exist in your **application.conf**
* for the passed `dbName`.
*
* @param dbName the name of a database in your **application.conf**.
* @return a Slick `DatabaseConfig` instance for the requested database name.
*/
@throws(classOf[IllegalArgumentException])
@deprecated(
"Inject DatabaseConfigProvider using @Named(\"dbName\") and call get[P] or use SlickApi#dbConfig[P](name)",
"3.0.0"
)
def get[P <: BasicProfile](dbName: String)(implicit app: Application): DatabaseConfig[P] =
DatabaseConfigLocator(dbName)
}
/**
* Mix-in this trait if you need a Slick database and profile. This is useful if you need to define a Slick
* table or need to execute some operation in the database.
*
* There is only one abstract field, `dbConfig`, which you can implement by calling `DatabaseConfigProvider.get`.
* If you are injecting `DatabaseConfigProvider` instances using dependency injection, prefer using the trait
* `HasDatabaseConfigProvider` instead of this one.
*
* ==Example==
*
* {{{
* // model definition
* class Cat(name: String, color: String)
* // DAO definition
* class CatDAO extends HasDatabaseConfig[RelationalProfile] {
* protected val dbConfig = DatabaseConfigProvider.get[RelationalProfile](Play.current)
* import profile.api._
*
* private val Cats = TableQuery[CatsTable]
* def all() = db.run(Cats.result)
* def insert(cat: Cat) = db.run(Cats += cat)
*
* // Slick table definition
* private class CatsTable(tag: Tag) extends Table[Cat](tag, "CAT") {
* def name = column[String]("NAME", O.PrimaryKey)
* def color = column[String]("COLOR")
* def * = (name, color) <> (Cat.tupled, Cat.unapply _)
* }
* }
* }}}
*
* Of course, you do not need to define a DAO to use this trait (the above it is really just an example of usage).
*/
trait HasDatabaseConfig[P <: BasicProfile] {
/** The Slick database configuration. */
protected val dbConfig: DatabaseConfig[P] // field is declared as a val because we want a stable identifier.
/** The Slick profile extracted from `dbConfig`. */
protected final lazy val profile: P = dbConfig.profile // field is lazy to avoid early initializer problems.
@deprecated("Use `profile` instead of `driver`", "2.1")
protected final lazy val driver: P = dbConfig.profile // field is lazy to avoid early initializer problems.
/** The Slick database extracted from `dbConfig`. */
protected final def db: P#Backend#Database = dbConfig.db
}
/**
* Mix-in this trait if you need a Slick database and profile, and you are using dependency injection for obtaining
* an instance of `DatabaseConfigProvider`. If you are not using dependency injection, then prefer mixing
* `HasDatabaseConfig` instead.
*
* This trait is useful if you need to define a Slick table or need to execute some operation in the database.
*
* ==Example==
*
* {{{
* // model definition
* class Cat(name: String, color: String)
* // DAO definition
* class CatDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[RelationalProfile] {
* import profile.api._
*
* private val Cats = TableQuery[CatsTable]
* def all() = db.run(Cats.result)
* def insert(cat: Cat) = db.run(Cats += cat)
*
* // Slick table definition
* private class CatsTable(tag: Tag) extends Table[Cat](tag, "CAT") {
* def name = column[String]("NAME", O.PrimaryKey)
* def color = column[String]("COLOR")
* def * = (name, color) <> (Cat.tupled, Cat.unapply _)
* }
* }
* }}}
*
* Of course, you do not need to define a DAO to use this trait (the above it is really just an example of usage).
*/
trait HasDatabaseConfigProvider[P <: BasicProfile] extends HasDatabaseConfig[P] {
/** The provider of a Slick `DatabaseConfig` instance. */
protected val dbConfigProvider: DatabaseConfigProvider
protected final override lazy val dbConfig: DatabaseConfig[P] =
dbConfigProvider.get[P] // field is lazy to avoid early initializer problems.
}