我遇到的例子是没有主键的关系,我的数据库模式如下。
我在两个表中都有主键,并且我正尝试创建一个DAO方法,该方法将连接user表和department表以显示一条记录。
- 问题**,如何创建一个DAO方法来访问由部门信息连接的记录。如果可能的话,我更喜欢不创建更多的数据类。例如使用
Map<User, Department>
。如果没有,我将接受其他解决方案。
- 问题**,如何创建一个DAO方法来访问由部门信息连接的记录。如果可能的话,我更喜欢不创建更多的数据类。例如使用
- 用户表**
+----+----------+----------+---------------+
| id | username | name | department_id |
+----+----------+----------+---------------+
| 1 | johndoe | John Doe | 3 |
| 2 | janedoe | Jane Doe | 4 |
+----+----------+----------+---------------+
- 用户数据类**
@Entity(tableName = "user")
data class User(
@PrimaryKey (autoGenerate = true) var id: Long,
var username: String,
var name: String,
var department_id: Long)
- 部门表**
+----+----------------+
| id | name |
+----+----------------+
| 1 | Sales |
| 2 | Account |
| 3 | Human Resource |
| 4 | Marketing |
+----+----------------+
- 部门数据类**
@Entity(tableName = "department")
data class Department(
@PrimaryKey(autoGenerate = true) var id: Long,
var name: String)
"我对DAO的尝试"
@Dao
interface UserDAO {
@Query("SELECT user.*, department.name AS 'department_name' FROM user " +
"INNER JOIN department ON user.department_id = department.id " +
"WHERE user.id = :id")
fun findById(id: Long): Map<User, Department>
}
- 编辑**
如果Department是在User内部组成的,它会起作用吗?如果是这样的话,那么DAO内部的查询看起来会是什么样子?
@Entity(tableName = "user")
data class User(
@PrimaryKey (autoGenerate = true) var id: Long,
var username: String,
var name: String,
@Embedded var department: Department)
data class Department(
@PrimaryKey(autoGenerate = true)
var id: Long,
var name: String? = null): Parcelable
- DAO尝试**
@Query("SELECT * FROM user " +
"INNER JOIN department d ON department.id = d.id " +
"WHERE id = :id")
fun findById(id: Long): Map<User, Department>
3条答案
按热度按时间1mrurvl11#
由于列名(id和name)不明确,您的代码按但是的方式工作,值与预期不符。
以下是调试时的结果(注意用户ID是500和501,而不是1和2,以便更好地突出显示问题),断点位于适当的位置,并且使用:-
然后调试器显示:-
也就是说,尽管John的部门ID是3,但在部门本身中却是500,同样,部门名称是***John Doe***,而不是预期的*Human Resource。
这是因为Room不知道哪个id代表什么,同样也不知道name。
修复方法是使用唯一的列名,例如:-
显然,如果列名发生变化,则SQL必须相应地进行更改,因此:-
现在调试显示:-
其他重新编辑
如果部门是在用户内部组成的,是否可以?
如果您在
@Entity
注解类(包含在@Database
注解类的entities
参数中)中使用@Embedded
,则生成的表将具有与嵌入类相同的列。如果嵌入的类以前是一个表,那么就不存在的关系而言,以前的表很可能是失效的。
嵌入的Department存在一个问题,因为您将有两列名为id
从数据库的Angular 来看,如果是一对多关系,则相同的数据(例如人力资源)将重复,这与标准化相反。
关于这个问题
那么这将不起作用,因为没有department表(因为根据您的代码,Department类没有用
@Entity
注解)。pxy2qtax2#
正如官方文档中所描述的,房间从
2.4
版本开始就支持这个功能。与您类似的问题似乎也在这个答案https://stackoverflow.com/a/72990697/5473567中得到了解决在你的具体例子中,你忘记了关系是1:N,因此你在DAO函数中的返回类型应该看起来像
Map<User, List<Department>>
。SELECT中的
department.name AS 'department_name'
也是错误的。data class Department
中的字段name
名为name,因此在数据库表department中,此字段也将名为name。如果要将其名称更改为SELECT中使用的department_name
,你必须使用注解@ColumnInfo
,如下所示:最后一个提示,如果您正在从数据库中提取完整的数据,那么有足够的数据可以使用
SELECT * FROM...
,Room将为您解决这个问题。最后,整个DAO接口可能看起来像这样:
ozxc1zmp3#
解决了。根据答案,下面是我的解决方案,不使用额外的数据类,同时保持列名不变,例如在每个表中使用不带任何前缀的
id
列(更可取)。我不得不在WHERE
子句中使用user.id
以避免歧义