按照Exposed提供的示例,我无法在创建它的事务之外读取创建的表/数据.我正在使用h2-in-memory数据库.
例外是:
Exception in thread "main" org.h2.jdbc.JdbcSQLException: Table "CITIES" not found; SQL statement:
Run Code Online (Sandbox Code Playgroud)
我已经添加了一个提交调用,但这没有帮助.如果我在创建数据的事务中读取数据,就像在github链接上的示例一样,它可以正常工作.这是它的简化版本:
fun main(args: Array<String>) {
Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver")
transaction {
create(Cities)
City.new {
name = "St. Petersburg"
}
println("Cities: ${City.all().joinToString { it.name }}")
//I have added this commit here
commit()
}
//I want to read the data outside the transaction, but it does not work
transaction {
println("Cities: ${City.all().joinToString { it.name }}")
}
}
Run Code Online (Sandbox Code Playgroud)
我该如何保存数据?
添加logger.addLogger(StdOutSqlLogger)提供以下输出:
SQL: CREATE TABLE IF NOT EXISTS …Run Code Online (Sandbox Code Playgroud) 我有以下用户表对象和实体类:
object UserTable : IntIdTable() {
val name = varchar("name", 256)
}
class User(id: EntityID<Int>): IntEntity(id) {
companion object : IntEntityClass<User>(UserTable)
val name by UserTable.name
}
Run Code Online (Sandbox Code Playgroud)
有没有办法使用 Gson(或其他一些库)将 JSON 解析为一个User实例,然后插入它?据我所知,似乎我必须创建一个中间UserData数据类,然后手动复制字段。
data class UserData {
var id: Int?
var name: String?
}
fun main() {
val data = Gson().fromJson<UserData>("...", UserData::class.java)
val user = User.new {
name = data.name
}
}
Run Code Online (Sandbox Code Playgroud)
在这个人为的例子中并不是那么糟糕,但我想知道是否有更干燥的方法。
当尝试从 my 获取第一行时transaction,我收到错误:
java.lang.IllegalStateException:上下文中没有事务。
我的代码如下所示:
fun loadPlayer(client: Client): PlayerLoadResult {
var player = transaction {
PlayerModel.select {
PlayerModel.username eq client.loginUsername
}
}.firstOrNull() ?: return PlayerLoadResult.NEW_ACCOUNT
// ...
return PlayerLoadResult.LOAD_ACCOUNT
}
Run Code Online (Sandbox Code Playgroud)
我的PlayerModel看起来像这样:
object PlayerModel : Table("Players") {
val id = integer("id").autoIncrement().primaryKey()
val username = varchar("username", 60).uniqueIndex()
val displayName = varchar("display_name", 60).uniqueIndex()
val x = integer("position_x")
val height = integer("position_y")
val z = integer("position_z")
val privilege = integer("privilege").default(1)
val runEnergy = float("run_energy").default(100.toFloat())
val displayMode = integer("display_mode").default(0)
val hash …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 Kotlin Exposed 将记录批量插入到 SQL 表中。我已经按照公开文档设置了代码,但是,正在执行的 SQL 语句是单独的插入语句而不是 1 个批量插入语句。
位于此处的文档: https: //github.com/JetBrains/Exposed/wiki/DSL 有关批量插入的内容如下:
批量插入
批量插入允许在一个 sql 语句中将实体列表映射到数据库原始数据中。它比一条一条插入效率更高,因为它只启动一条语句。这是一个例子:
val cityNames = listOf("Paris", "Moscow", "Helsinki")
val allCitiesID = cities.batchInsert(cityNames) { name ->
this[cities.name] = name
}
Run Code Online (Sandbox Code Playgroud)
我的代码如下:
val mappings: List<Triple<String, String, String>> = listOf(triple1, triple2, triple3)
transaction {
TableName.batchInsert(mappings) {
this[TableName.value1] = it.first
this[TableName.value2] = it.second
this[TableName.value3] = it.third
}
}
Run Code Online (Sandbox Code Playgroud)
我期望看到打印的是 1 个批量插入语句,其语法如下
INSERT INTO TableName (value1, value2, value3) values
(triple1value1, triple1value2, triple1value3),
(triple2value1, triple2value2, triple2value3),
(triple3value1, triple3value2, triple3value3), ... …Run Code Online (Sandbox Code Playgroud) 我尝试做的是获取有关游戏中英雄的大量数据并将其保存在数据库中,我使用 OkHttp 向服务器发出请求并使用 gson 解析 json,然后将我从 gson 获得的类保存到数据库中通过使用来自 Jetbrains 的名为 Exposed 的 ORM。调用在循环中进行,对于每个英雄将有 500 个关于他们最后一场比赛的结果,有 115 个英雄,我让线程在每个请求前休眠 1 秒。该应用程序开始运行得非常快,我什至无法在控制台中读取结果,但过了一会儿我得到了这个:
I/zygote: Background concurrent copying GC freed 72775(3MB) AllocSpace objects, 5(5MB) LOS objects, 49% free, 5MB/11MB, paused 416us total 1.664s
Run Code Online (Sandbox Code Playgroud)
然后应用程序运行得非常慢,我在数据库中获得 1 个条目/秒,那时我希望获得另一个 15000。在 logcat 中,我也得到了这个
03-29 12:01:00.050 1634-1651/? W/android.os.Debug: failed to get memory consumption info: -1
03-29 12:01:00.059 1634-1651/? E/memtrack: Couldn't load memtrack module
Run Code Online (Sandbox Code Playgroud)
应用程序没有崩溃,它只是变得非常慢,有趣的是,当我重新启动应用程序时,它立即变慢,第一次在 10 分钟后变慢,但后来一直很慢。同样在我重新启动后,它会写出类似的东西
V/StudioProfiler: Loaded classes: 8137
Run Code Online (Sandbox Code Playgroud)
如果应用程序刚刚启动,为什么会加载这么多类,这意味着什么我是初学者,我真的不明白这一切。有任何想法吗?
谢谢你。
我可以在 Kotlin 公开库上找到的所有材料都假设该表有一个主标识列,因此在大多数示例中显示的实体继承了IntEntity抽象类。例如:
class UserLocation(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<UserLocation>(UserLocations)
var userId by UserLocations.userId
var user by User referencedOn UserLocations.user
var recordedAt by UserLocations.recordedAt
var insertedAt by UserLocations.insertedAt
var point by UserLocations.point
Run Code Online (Sandbox Code Playgroud)
这对应于这个表定义:
object UserLocations : IntIdTable("user_locations") {
val userId = integer("user_id")
val user = reference("user_id", Users)
val recordedAt = datetime("recorded_at").nullable()
val insertedAt = datetime("inserted_at")
val point = point("point")
}
Run Code Online (Sandbox Code Playgroud)
问题是,我的表实际上没有标识列。我知道没有主键的表的所有负面影响,但不幸的是我只能读取该表。我无法获得对该表的写访问权以添加主键。
在公开库的 wiki 中,它提到对象表定义可以继承Table而IntIdTable不是IntEntity.
我的问题:当表没有 id 列时,我的实体应该继承(而不是 …
我想在使用值进行复杂连接时添加自定义字段\n基本上是这样的:
\nSELECT p.first_name, "Smith" AS "last_name" \nFROM person p\nWHERE first_name = "John"\nRun Code Online (Sandbox Code Playgroud)\n在 kotlin 中,会是这样的:
\nPersonTable\n .slice(PersonTable.first_name, "" HERE IS WHERE I\xe2\x80\x99D LIKE TO PUT SOMETHING "")\n .select(PersonTable.first_name eq "John")\nRun Code Online (Sandbox Code Playgroud)\n此示例中的任何表中都不存在字段“last_name”。我想将它添加到 ResultRow 中。
\n我真正的查询要复杂得多,但我无法公开共享它。\n基本上我想要的是将 last_name 列添加到我将从查询中得到的值为“Smith”的每个 ResultRow。然后是稍后访问该列的方法。
\n这可以在 JetBrains Exposed 中完成吗?
\n这是我尝试过但不成功的方法:
\nPersonTable\n .slice(PersonTable.first_name, stringLiteral("Smith").alias("last_name"))\n .select(PersonTable.first_name eq "John")\nRun Code Online (Sandbox Code Playgroud)\n上面的内容并没有按照我想要的方式工作。它确实添加了一个值为“Smith”的列,但列名称/别名是“Smith”last_name,而不仅仅是last_name。这不起作用的原因是我将与另一个选择进行联合,该选择将具有不同的 last_name 值,因此我需要这两个选择中的列名称相同。
\n我知道您通常可以从 Java 调用 Kotlin 代码,但是在进行 Exposed 时值得这样做吗?或者它的 API 是否过于依赖 Kotlin 的惯用编码方式。
有没有人有使用 Java 代码中的 Kotlin Exposed 的经验?而且玩得好吗?
我环顾四周,但似乎无法找到如何使用 Kotlin 的 Exposed SQL 框架“在不存在时插入”或“在冲突时插入”。我目前正在编写原始 SQL 语句并按原样执行它们。我认为在某些情况下我无法避免这种情况,但如果可能的话,我更愿意使用该框架。我没有看到 DSL 或 DAO 语法的任何选项。
编辑:
对于可能遇到此问题的任何人,Tapac 的评论对我有用。
将 Table.insertIgnore() 用于“如果不存在则插入”,并且在https://github.com/JetBrains/Exposed/wiki/FAQ#q-is-upsert-supported 中存在一个 upsert 示例。
我在 Kotlin JVM 项目上使用Exposed作为 O/R Mapper。(版本:0.17.6)
当我从 DAO API 获取外键列的值(由 Exposed 方法定义的列)时,我遇到了 N+1 查询问题reference。
我用解决方法代码以某种方式解决了问题,但是有人知道正确的解决方案吗?
情况是这样的。
有两个表(users、user_addresses),一个表(user_addresses 表)在另一个表(user 表)上有外键引用。
object Users : LongIdTable("users") {
val name = varchar("name", 30)
}
class User(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<User>(Users)
var name by Users.name
}
object UserAddresses : LongIdTable("user_addresses") {
val user = reference("user_id", Users)
val address = varchar("address", 30)
}
class UserAddress(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<UserAddress>(UserAddresses)
var user by User.referencedOn(UserAddresses.user)
var …Run Code Online (Sandbox Code Playgroud) kotlin-exposed ×10
kotlin ×8
gson ×2
android ×1
java ×1
json ×1
mysql ×1
okhttp ×1
postgresql ×1
primary-key ×1
sql ×1
transactions ×1