休眠中的 CRUD 给出 table 未映射异常
CRUD in hibernate giving table not mapped exception
我正在尝试在 hibernate.However 中实施 CRUD 操作,但出现 "Table not mapped" 错误。而且,Query 即将在我的代码中弃用。
据我所知,table的映射是这样实现的only.Then,这里有什么问题吗?
代码
public void deleteTeacher(String name) {
Transaction tx = null;
Session session = Utility.getSessionFactory().openSession();
tx = session.beginTransaction();
Query query = session.createQuery("from vi where name=" + name);
//Teacher teacher=(Teacher)session.get(Teacher.class, name);
Teacher teacher = (Teacher) query.getSingleResult();
session.delete(teacher);
session.getTransaction().commit();
session.close();
}
错误
Exception in thread "main" java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: vi is not mapped [from vi where name=Aayushi]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:131)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:658)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:102)
at DAO.deleteTeacher(DAO.java:45)
at MainClass.main(MainClass.java:37)
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: vi is not mapped [from vi where name=Aayushi]
at org.hibernate.hql.internal.ast.QuerySyntaxException.generateQueryException(QuerySyntaxException.java:79)
at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:217)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:541)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:650)
... 3 more
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: vi is not mapped
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:171)
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:91)
at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:79)
at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:324)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3696)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3585)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:720)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:576)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:266)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
... 9 more
而配置类是
teacher.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping>
<class name="Teacher" table="vi">
<composite-id>
<key-property name="name" column="name" />
<key-property name="subject" column="subject" length="10" />
</composite-id>
</class>
</hibernate-mapping>
在 HQL 中,您必须使用 class 个名称,而不是 table 个名称,因此您的查询必须是:
"from Teacher where name="+Name
你还应该使用参数绑定,以防止SQL注入
字符串应介于 ''
之间,因此您的查询应如下所示:
Query query=session.createQuery("from vi where name='" + name + "');
但为了避免任何语法错误或 SQL 注入,您必须使用:
Query query = session.createQuery("from vi where name=:name");
query.setParameter("name", name);
编辑
为什么你根本不使用:
//no need to select your object before you delete it
//Query query = session.createQuery("from vi where name=" + name);
//Teacher teacher=(Teacher)session.get(Teacher.class, name);
//Teacher teacher = (Teacher) query.getSingleResult();
//just make a delete query directly
String hql = "DELETE FROM vi WHERE name= :name";
Query query = session.createQuery(hql);
query.setParameter("name", name);
int result = query.executeUpdate();
避免在删除之前select,如果结果为空,可能会导致此错误。
根据您的模型,您在这里做出了一些糟糕的假设。您的 Teacher
模型使用 name
和 subject
的复合键,但您的代码假定按名称定位 Teacher
会获得单行结果,而这只是'它永远是真的。
您需要调整您的数据模型并强制 name
在所有 Teacher
实体中保持唯一,这在现实世界中同样没有意义,或者修改您的删除解释这一点的代码。
以下代码采用 Hibernate 5.2,因此可能需要进行一些小的调整,但无论如何前提都完全相同:
final List<Teacher> teachers = session
.createQuery( "FROM Teacher t WHERE t.name = :name", Teacher.class )
.setParameter( "name", teacherName )
.getResultList();
for ( Teacher teacher : teachers ) {
session.remove( teacher );
}
@YCF_L关于删除之前的select的观点,其实是不是如果您的代码考虑了查询结果 可以 为空的事实,则会出现问题。但是因为按照上面的真实场景,多个老师 可以 有相同的名字,它不会给你一个错误,因为 returned List<>
会在跳过删除 for 循环时为空,或者包含值并执行删除 for 循环。
如前所述,如果您愿意,您可以盲目执行删除而不获取数据,这样看起来会非常相似。
int deleteCount = session
.createQuery( "DELETE FROM Teacher t WHERE t.name = :name" )
.setParameter( "name", teacherName )
.executeUpdate();
在这种情况下,您可以使用 return 值 deleteCount
来记录有多少教师被删除,或者如果该值可能 不是 [=42],则执行一些特定代码=]如你所料。
最后,虽然其他人指出了使用参数绑定来避免 SQL 注入的好处,但由于许多其他原因,参数绑定也很重要。
例如,绑定参数 SQL 可以由您的数据库进行优化、规划和缓存,并在以后的查询中重复使用。当您直接将实际值引入 SQL 时,大多数数据库平台会按原样缓存查询,因此只有在使用相同参数提供与之前完全相同的 SQL 时才能获得此好处。
我正在尝试在 hibernate.However 中实施 CRUD 操作,但出现 "Table not mapped" 错误。而且,Query 即将在我的代码中弃用。 据我所知,table的映射是这样实现的only.Then,这里有什么问题吗?
代码
public void deleteTeacher(String name) {
Transaction tx = null;
Session session = Utility.getSessionFactory().openSession();
tx = session.beginTransaction();
Query query = session.createQuery("from vi where name=" + name);
//Teacher teacher=(Teacher)session.get(Teacher.class, name);
Teacher teacher = (Teacher) query.getSingleResult();
session.delete(teacher);
session.getTransaction().commit();
session.close();
}
错误
Exception in thread "main" java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: vi is not mapped [from vi where name=Aayushi]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:131)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:658)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:102)
at DAO.deleteTeacher(DAO.java:45)
at MainClass.main(MainClass.java:37)
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: vi is not mapped [from vi where name=Aayushi]
at org.hibernate.hql.internal.ast.QuerySyntaxException.generateQueryException(QuerySyntaxException.java:79)
at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:217)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:541)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:650)
... 3 more
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: vi is not mapped
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:171)
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:91)
at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:79)
at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:324)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3696)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3585)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:720)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:576)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:266)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
... 9 more
而配置类是
teacher.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping>
<class name="Teacher" table="vi">
<composite-id>
<key-property name="name" column="name" />
<key-property name="subject" column="subject" length="10" />
</composite-id>
</class>
</hibernate-mapping>
在 HQL 中,您必须使用 class 个名称,而不是 table 个名称,因此您的查询必须是:
"from Teacher where name="+Name
你还应该使用参数绑定,以防止SQL注入
字符串应介于 ''
之间,因此您的查询应如下所示:
Query query=session.createQuery("from vi where name='" + name + "');
但为了避免任何语法错误或 SQL 注入,您必须使用:
Query query = session.createQuery("from vi where name=:name");
query.setParameter("name", name);
编辑
为什么你根本不使用:
//no need to select your object before you delete it
//Query query = session.createQuery("from vi where name=" + name);
//Teacher teacher=(Teacher)session.get(Teacher.class, name);
//Teacher teacher = (Teacher) query.getSingleResult();
//just make a delete query directly
String hql = "DELETE FROM vi WHERE name= :name";
Query query = session.createQuery(hql);
query.setParameter("name", name);
int result = query.executeUpdate();
避免在删除之前select,如果结果为空,可能会导致此错误。
根据您的模型,您在这里做出了一些糟糕的假设。您的 Teacher
模型使用 name
和 subject
的复合键,但您的代码假定按名称定位 Teacher
会获得单行结果,而这只是'它永远是真的。
您需要调整您的数据模型并强制 name
在所有 Teacher
实体中保持唯一,这在现实世界中同样没有意义,或者修改您的删除解释这一点的代码。
以下代码采用 Hibernate 5.2,因此可能需要进行一些小的调整,但无论如何前提都完全相同:
final List<Teacher> teachers = session
.createQuery( "FROM Teacher t WHERE t.name = :name", Teacher.class )
.setParameter( "name", teacherName )
.getResultList();
for ( Teacher teacher : teachers ) {
session.remove( teacher );
}
@YCF_L关于删除之前的select的观点,其实是不是如果您的代码考虑了查询结果 可以 为空的事实,则会出现问题。但是因为按照上面的真实场景,多个老师 可以 有相同的名字,它不会给你一个错误,因为 returned List<>
会在跳过删除 for 循环时为空,或者包含值并执行删除 for 循环。
如前所述,如果您愿意,您可以盲目执行删除而不获取数据,这样看起来会非常相似。
int deleteCount = session
.createQuery( "DELETE FROM Teacher t WHERE t.name = :name" )
.setParameter( "name", teacherName )
.executeUpdate();
在这种情况下,您可以使用 return 值 deleteCount
来记录有多少教师被删除,或者如果该值可能 不是 [=42],则执行一些特定代码=]如你所料。
最后,虽然其他人指出了使用参数绑定来避免 SQL 注入的好处,但由于许多其他原因,参数绑定也很重要。
例如,绑定参数 SQL 可以由您的数据库进行优化、规划和缓存,并在以后的查询中重复使用。当您直接将实际值引入 SQL 时,大多数数据库平台会按原样缓存查询,因此只有在使用相同参数提供与之前完全相同的 SQL 时才能获得此好处。