The abstract schema type 'Entity' is unknown.

本文解决了一个JPA查询异常问题,该问题源于实体类定义错误。通过修正实体类上的@Table注解,成功解决了未知的抽象模式类型异常,并确保了JPQL查询能够正确执行。

异常栈:

An exception occurred while creating a query in EntityManager: 
Exception Description: Problem compiling [SELECT u FROM User u WHERE u.name=:Name AND u.pswd=:Pswd]. 
[14, 18] The abstract schema type 'User' is unknown.
[27, 33] The state field path 'u.name' cannot be resolved to a valid type.
[46, 52] The state field path 'u.pswd' cannot be resolved to a valid type.
java.lang.IllegalArgumentException
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1605)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:366)
    at com.sun.proxy.$Proxy16.createQuery(Unknown Source)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
    at com.sun.proxy.$Proxy16.createQuery(Unknown Source)
    at net.lab.dao.impl.UserDaoImpl.getUser(UserDaoImpl.java:45)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
    at com.sun.proxy.$Proxy17.getUser(Unknown Source)
    at net.lab.test.UserTest.hello(UserTest.java:45)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildException(HermesParser.java:155)
    at org.eclipse.persistence.internal.jpa.jpql.HermesParser.validate(HermesParser.java:347)
    at org.eclipse.persistence.internal.jpa.jpql.HermesParser.populateQueryImp(HermesParser.java:278)
    at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildQuery(HermesParser.java:163)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:142)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:116)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:102)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:86)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1603)

用Junit测试jpa时的代码:

package net.lab.test;

import java.util.List;
import net.lab.dao.UserDao;
import net.lab.entity.User;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
 *
 * @author xiaofanku
 */
public class UserTest extends AbstractTests implements ApplicationContextAware{

    private ApplicationContext applicationContext;
    private UserDao ud;

    @Before
    public void init(){
        ud=applicationContext.getBean(UserDao.class);
    }
    // TODO add test methods here.
    // The methods must be annotated with annotation @Test. For example:
    //ngunit
    @Test
    public void hello() {
        User qu=ud.getUser("pktmandy", "12345");
        assertTrue(qu.getId()>0);
    }

    @Override
    public void setApplicationContext(ApplicationContext ac) throws BeansException {
        applicationContext=ac;
    }
}

实体类:

package net.lab.entity;

import java.io.Serializable;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
 * 购买者
 * @author xiaofanku
 */
@Entity(name="king_user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    /**
     * 用户名
     */
    @Column
    private String name;
    /**
     * 密码
     */
    @Column
    private String pswd;

    //GET/SET

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 11 * hash + Objects.hashCode(this.id);
        hash = 11 * hash + Objects.hashCode(this.name);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final User other = (User) obj;
        if (!Objects.equals(this.name, other.name)) {
            return false;
        }
        if (!Objects.equals(this.pswd, other.pswd)) {
            return false;
        }
        if (!Objects.equals(this.id, other.id)) {
            return false;
        }
        return true;
    }

}

DAO实现类:

package net.lab.dao.impl;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import net.lab.dao.UserDao;
import net.lab.entity.User;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author xiaofanku
 */
@Repository
public class UserDaoImpl implements UserDao{
    private EntityManager em;

    @PersistenceContext
    public void setEntityManager(EntityManager em) { 
        this.em=em;
    }   
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    @Override
    public long add(User user) {
        em.persist(user);
        return user.getId();
    }

    @Override
    public List<User> getAll() {
        return em.createQuery("SELECT u FROM User u").getResultList();
    }

    @Override
    public User getUser(String name, String pswd) {
        TypedQuery<User> q=em.createQuery("SELECT u FROM User u WHERE u.name=:Name AND u.pswd=:Pswd",User.class);
        q.setParameter("Name", name);
        q.setParameter("Pswd",pswd);
        return q.getResultList().get(0);
    }

    @Override
    public User getUser(long uid) {
        return em.find(User.class, uid);
    }

}

只需要改下User实体的注解,修改后:

package net.lab.entity;

import java.io.Serializable;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
 * 购买者
 * @author xiaofanku
 */
@Entity
@Table(name="king_user")
public class User implements Serializable {
//...
}

再运行测试文件
这里写图片描述

注意:
如果没有@Table注解(也就是表名加在Entity注解中),Dao中的以下方法是不会报异常的:

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    @Override
    public long add(User user) {
        em.persist(user);
        return user.getId();
    }
    @Override
    public User getUser(long uid) {
        return em.find(User.class, uid);
    }

其它两个方法报异常的共同点它们都使用了 Java Persistence query language (JPQL),在EE中有如下介绍:

Query Language Terminology

The following list defines some of the terms referred to in this chapter:

  • Abstract schema: The persistent schema abstraction (persistent entities, their state, and their >relationships) over which queries
    operate. The query language translates queries over this >persistent
    schema abstraction into queries that are executed over the database
    schema to which >entities are mapped.

  • Abstract schema type: The type to which the persistent property of an entity evaluates in the >abstract schema. That is, each
    persistent field or property in an entity has a corresponding state
    field of the same type in the abstract schema. The abstract schema type of an entity is derived >from the entity class and the metadata
    information provided by Java language annotations.

  • Backus-Naur Form (BNF): A notation that describes the syntax of high-level languages. The >syntax diagrams in this chapter are in BNF
    notation.

  • Navigation: The traversal of relationships in a query language expression. The navigation >operator is a period.

  • Path expression: An expression that navigates to a entity’s state or relationship field.

  • State field: A persistent field of an entity.

  • Relationship field: A persistent relationship field of an entity whose type is the abstract schema type of the related entity.

环境:
JDK: 1.7.0_79
Spring: 3.2.7
EclipseLink: 2.1
JUnit: 4.12

参考网址:
JPA’s Nasty “Unknown abstract schema type” Error
The Java EE 6 Tutorial

<think>我们遇到了一个特定的错误:当在DBeaver中成功连接OpenEdge数据库后,执行SQL查询时报错:"Receiverclasscom.ddtek.jdbc.openedgebase.ddaedoesnotdefineorinheritanimplementationoftheresolvedmethod'abstractvoidsetSchema(java.lang.String)'ofinterfacejava.sql.Connection"。这个错误表明,DBeaver尝试调用`Connection.setSchema(Stringschema)`方法,但是使用的OpenEdgeJDBC驱动(`com.ddtek.jdbc.openedgebase.ddae`)并没有实现这个方法。在Java中,如果一个类没有实现接口中定义的方法,就会抛出这样的抽象方法错误。###原因分析1.**JDBC驱动版本问题**:OpenEdgeJDBC驱动可能较旧,不支持JDBC4.1(或更高版本)中引入的`setSchema`方法。`setSchema`方法是在JDBC4.1(Java7)中引入的。2.**DBeaver的默认行为**:DBeaver在连接数据库时可能会尝试设置当前模式(schema),而如果驱动不支持该方法,就会报错。###解决方案####方案1:升级OpenEdgeJDBC驱动-**检查并升级驱动**:访问Progress官网下载最新版的OpenEdgeJDBC驱动。新版本可能已经实现了`setSchema`方法。-**操作步骤**:1.在DBeaver的驱动管理器中,找到之前配置的OpenEdge驱动。2.移除旧的驱动JAR文件,添加新下载的驱动JAR文件。3.测试连接并执行查询。####方案2:在DBeaver中禁用设置Schema的操作如果升级驱动不可行,我们可以尝试配置DBeaver,使其不调用`setSchema`方法。DBeaver允许通过连接设置来禁用自动设置schema的功能。-**操作步骤**:1.在DBeaver中,打开数据库连接配置(编辑连接)。2.转到“连接设置”中的“驱动属性”选项卡(或类似标签,具体名称可能因DBeaver版本而异)。3.添加一个自定义属性,用于关闭自动设置schema的行为。根据经验,我们可以尝试设置以下属性:-**属性名**:`defaultSchema`-**属性值**:留空或设置为当前用户默认的模式(如果知道的话)或者,查找是否有专门控制是否设置schema的属性。如果没有直接属性,我们可以尝试:4.在“初始化”选项卡(或类似名称)中,设置一个初始化SQL语句,例如:```sqlSETSCHEMA'your_schema_name';--如果知道需要使用的schema,可以在此设置```这样,当连接建立时,会执行这个SQL语句来设置schema,而避免使用JavaAPI。5.如果上述方法无效,可以尝试在DBeaver的配置文件中修改连接行为(不推荐,除非必要)。####方案3:修改DBeaver的源码或使用补丁(不推荐)由于DBeaver是开源软件,理论上可以修改其源码以避免调用`setSchema`方法。但这需要较高的技术能力,且维护困难,一般不推荐。###临时解决方法如果上述方案都不可行,可以尝试以下临时方法:-**使用旧版DBeaver**:有时新版DBeaver增加了新功能(如自动设置schema),而旧版可能没有该行为。尝试降级到旧版DBeaver。-**使用其他JDBCURL参数**:在连接URL中添加参数,尝试规避问题。例如,参考引用[1]中解决h2数据库连接问题的思路(添加`;OLD_INFORMATION_SCHEMA=TRUE`),我们可以尝试在OpenEdge的JDBCURL中添加一些特定参数。具体参数需要查阅OpenEdgeJDBC文档。例如:```jdbc:datadirect:openedge://host:port;databaseName=db;someParameter=value```###验证-修改配置后,重新连接并执行查询,观察是否还会报错。###参考-引用[1]中提到,对于h2数据库,通过添加`;OLD_INFORMATION_SCHEMA=TRUE`解决了类似问题。这提示我们可以尝试在连接参数中添加特定参数来规避问题[^1]。-引用[3]中关于驱动下载和安装的方法,如果驱动问题,可以尝试重新下载或更新驱动[^3]。§§相关问题§§1.如何查找OpenEdgeJDBC驱动的官方下载地址?2.在DBeaver中如何配置连接初始化SQL?3.如何查看OpenEdgeJDBC驱动支持的连接参数?</think>### 解决 DBeaver 连接 OpenEdge 后执行 SQL 报错 "Connection.setSchema 未实现" #### 错误原因分析 该错误表明 OpenEdge JDBC 驱动未实现 `setSchema()` 方法,而 DBeaver 在连接后默认会调用此方法设置数据库模式(schema)。核心原因是: 1. **驱动兼容性问题**:OpenEdge JDBC 驱动未完全实现 JDBC 4.x 规范中的 `java.sql.Connection` 接口[^1] 2. **DBeaver 默认行为**:DBeaver 连接后自动尝试设置 schema,但 OpenEdge 可能不需要此操作 3. **驱动版本过旧**:旧版驱动(如 DataDirect JDBC)存在接口实现不完整的问题 #### 解决方案 ##### 方法 1:禁用 DBeaver 的 schema 自动设置(推荐) 1. 在 DBeaver 中打开 OpenEdge 连接配置 2. 转到 **驱动属性** 选项卡 3. 添加以下自定义属性: ```properties property: defaultSchema value: <留空> ``` ```properties property: openDefaultSchema value: false ``` 4. 测试连接并执行查询 ##### 方法 2:修改连接初始化设置 1. 在连接配置中转到 **初始化** 选项卡 2. 在 "连接初始化" 区域添加 SQL 语句: ```sql SET SCHEMA 'pub' -- 替换为实际 schema 名称 ``` 3. 保存后重新连接 ##### 方法 3:升级 JDBC 驱动 1. 从 Progress 官网下载最新 OpenEdge JDBC 驱动 - 推荐版本:OpenEdge 12.x+ 的 `openedge.jar` 2. 在 DBeaver 驱动管理中替换旧驱动: ```mermaid graph TD A[驱动管理器] --> B[选择OpenEdge驱动] B --> C[移除旧JAR文件] C --> D[添加新openedge.jar] D --> E[测试连接] ``` ##### 方法 4:修改 JDBC URL 参数 在连接 URL 末尾添加禁用 schema 的参数: ```url jdbc:datadirect:openedge://host:port;databaseName=db;disableSetSchema=true ``` #### 验证步骤 1. 应用上述任一解决方案后 2. 执行测试 SQL: ```sql SELECT * FROM sysprogress.systables WHERE 1=0 ``` 3. 确认不再出现 `setSchema` 相关错误 #### 备选方案 若问题持续,可改用 Progress 官方工具: 1. **OpenEdge SQL Explorer**:内置管理工具 2. **Progress Developer Studio**:完整 IDE 支持 > ⚠️ 注意:若使用 DataDirect 驱动(`com.ddtek.jdbc`),建议替换为 Progress 官方驱动(`com.progress.sql.jdbc`)[^1]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值