java - Play Framework - Ebean - 没有为类 "class name"注册 ScalarType

标签 java mysql orm persistence ebean

我通过将自定义 Java 对象表示为表,使用持久性 API 和 Ebean 在 MySQL 数据库中构建了一些表。现在,我尝试通过在 Ebean.find() 查询中作为参数传递我想要的对象来恢复存储的条目,但每次都会抛出 javax.persistence.PersistenceException


让我解释一下层次结构:

有一个Machine类:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "MACHINE_TYPE")
public class Machine extends Model
{
    @Id
    @Column(name = "id")
    private Long _machineID;

    @Column(name = "name", unique = true)
    private String _name;

    @Column(name = "info")
    private String _info;

    // rest of code
}

有两个子类。一个 Server 类扩展 Machine 如下:

@Entity
@Table(name = "machine")
@DiscriminatorValue("Server")
public class Server extends Machine
{
   @Column(name = "ip")
   private String _ip;

   @Column(name = "port")
   private Integer _port;

   @Column(name = "user_name")
   private String _userName;

   @Column(name = "password")
   private String _password;

   @Column(name = "clock")
   private Integer _clock;

   @Column(name = "ram")
   private Integer _ram;

   // rest of code
}

还有一个容器类:

@Entity
@Table(name = "machine")
@DiscriminatorValue("Container")
public class Container extends Machine
{
@Column(name = "dockerID", unique = true)
   private String _dockerID;

   @ManyToOne
   @JoinColumn(name = "host", insertable = true, updatable = true)
   private Server _host;

   @Column(name = "currentSize")
   private String _currentSize;

   @Column(name = "additionalInfo")
   private String _additionalInfo;

   @Column(name = "last_login")
   private String _lastLogin;

   // rest of code
}

这段代码,在MySQL数据库中建立了一张机器表,如下所示:

`machine` (
  `machine_type` varchar(31) NOT NULL,
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `info` mediumtext,
  `dockerID` varchar(255) DEFAULT NULL,
  `host` bigint(20) DEFAULT NULL,
  `currentSize` varchar(255) DEFAULT NULL,
  `additionalInfo` text,
  `last_login` varchar(255) DEFAULT NULL,
  `ip` varchar(255) DEFAULT NULL,
  `port` int(11) DEFAULT NULL,
  `user_name` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `clock` int(11) DEFAULT NULL,
  `ram` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_machine_dockerID` (`dockerID`),
  KEY `ix_machine__host_4` (`host`),
  CONSTRAINT `fk_machine__host_4` FOREIGN KEY (`host`) REFERENCES `machine` (`id`)
)

这似乎是正确的。但是,如果我在数据库中添加一个条目并尝试执行

...
Server server = Server.getServerByName(serverName); // this returns a Server object correctly
List<Container> testCase = Ebean.find(Container.class)
                    .where()
                    .eq("host", server)
                    .findList(); // this throws the exception

我得到一个 PersistenceException 说:

javax.persistence.PersistenceException: No ScalarType registered for class com.project.models.Server
    at com.avaje.ebeaninternal.server.persist.Binder.bindObject(Binder.java:158)
    rest of the StackTrace

即使我尝试更改查询

List<Container> testcase = Ebean.find(Container.class)
                    .where()
                    .eq("host", server.getMachineId()) // pass the serverID
                    .findList();

我得到另一个异常表示:

javax.persistence.PersistenceException: Query threw SQLException:Column 'host' in where clause is ambiguous 
Bind values:[1] 
Query was:
select t0.machine_type c0, t0.id c1, t0.name c2, t0.info c3, t0.dockerID c4, t0.currentSize c5, 
t0.additionalInfo c6, t0.last_login c7, t1.machine_type c8, t0.host c9 from machine t0 
left outer join machine t1 on t1.id = t0.host and t1.machine_type = 'Server'  
where t0.machine_type = 'Container'  and host = ?  

任何帮助,至少对遵循的方向将不胜感激

最佳答案

所以,经过一些测试后,我发现如果你想访问包含对象的数据库表,你需要在你的对象映射中遵循一些规则,显然我没有。在文档中的任何地方我也找不到它。此解决方案是失败并尝试的结果。


首先,变量的名称必须与列的名称相同!如果我将 Container.classServer.class 变量更改为:

@ManyToOne
@JoinColumn(name = "host", insertable = true, updatable = true)
private Server host; // notice the name is the same as the column name

一切正常,我可以在查询中传递 Server.class 对象,例如:

Ebean.find(Container.class)
      .where()
      .eq("host", server)
      .findList();

因此要映射对象实体,列名必须与变量名完全相同,反之亦然。


其次,据我在文档中所读,我们可以在 @ManyToOne 注释中指定目标实体,如下所示:

@ManyToOne(targetEntity = Server.class) // explicitly specify the target class
@JoinColumn(name = "host", insertable = true, updatable = true)
private Server host;

虽然这不是我的主要问题,因为 Java 读取 host 字段的类类型并自动传递目标实体。但最好在这里保持安全。

关于java - Play Framework - Ebean - 没有为类 "class name"注册 ScalarType,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45032890/

相关文章:

python - 将 INSERT SQL 语句的无效值更改为 None 但出现 "Data Truncated"错误

scala - 如何在 Play 框架中使用 SORM 框架?

java - 如何通过JDBC连接两个数据库?是否可以?

java - WEKA classifyinstance 和 distributionforinstance 方法

java - 写C*超时以不可预测的方式出现

java - Hibernate 如何跟踪来自不同 session 的分离对象和持久对象

mysql - 使用 Django 将查询集中的查询分组为一个查询

java - 将Java对象转换为与D3的圆形包装图兼容的JSON

MySQL JSON_EXTRACT 路径表达式错误

php - 如何检测 MySQL 查询是否来自缓存?