не вдалося отримати ResultSet у сплячому режимі


80

У мене проблема з сплячим режимом . Я намагаюся розібрати в список , але він кидає виняток: HTTP Status 500 - could not extract ResultSet. Коли я налагоджую, це несправність на лінії query.list()...

Мій зразок коду тут

@Entity
@Table(name = "catalog")
public class Catalog implements Serializable {

@Id
@Column(name="ID_CATALOG")
@GeneratedValue 
private Integer idCatalog;

@Column(name="Catalog_Name")
private String catalogName;

@OneToMany(mappedBy="catalog", fetch = FetchType.LAZY)
private Set<Product> products = new HashSet<Product>(0);

//getter & setter & constructor
//...
}


@Entity
@Table(name = "product")
public class Product implements Serializable {

@Id
@Column(name="id_product")
@GeneratedValue 
private Integer idProduct;

@ManyToOne
@JoinColumn(name="ID_CATALOG")
private Catalog catalog;

@Column(name="product_name")
private String productName;

@Column(name="date")
private Date date;

@Column(name="author")
private String author;

@Column(name="price")
private Integer price;

@Column(name="linkimage")
private String linkimage;

//getter & setter & constructor
}



@Repository
@SuppressWarnings({"unchecked", "rawtypes"})
public class ProductDAOImpl implements ProductDAO {
    @Autowired
    private SessionFactory sessionFactory;
public List<Product> searchProductByCatalog(String catalogid, String keyword) {
    String sql = "select p from Product p where 1 = 1";
    Session session = sessionFactory.getCurrentSession();

    if (keyword.trim().equals("") == false) {
        sql += " and p.productName like '%" + keyword + "%'";
    }
    if (catalogid.trim().equals("-1") == false
            && catalogid.trim().equals("") == false) {
        sql += " and p.catalog.idCatalog = " + Integer.parseInt(catalogid);
    }
    Query query = session.createQuery(sql);
    List listProduct = query.list();
    return listProduct;
}

}

Моя квасоля

  <!-- Scan classpath for annotations (eg: @Service, @Repository etc) -->
  <context:component-scan base-package="com.shopmvc"/>

  <!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with 
       username root and blank password. Change below if it's not the case -->
  <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/shoesshopdb?autoReconnect=true"/>
    <property name="username" value="root"/>
    <property name="password" value="12345"/>
    <property name="validationQuery" value="SELECT 1"/>
  </bean>

  <!-- Hibernate Session Factory -->
  <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan">
      <array>
        <value>com.shopmvc.pojo</value>
      </array>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.MySQLDialect
      </value>
    </property>
  </bean>

  <!-- Hibernate Transaction Manager -->
  <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>

  <!-- Activates annotation based transaction management -->
  <tx:annotation-driven transaction-manager="transactionManager"/>

Виняток:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:948)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

root cause 

org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:82)
    org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:61)
    org.hibernate.loader.Loader.getResultSet(Loader.java:2036)

root cause 

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'product0_.ID_CATALOG' in 'field list'
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    java.lang.reflect.Constructor.newInstance(Unknown Source)
    com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    com.mysql.jdbc.Util.getInstance(Util.java:386)
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
    com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
    com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
    com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
    com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
    org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
    org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
    org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:56)
    org.hibernate.loader.Loader.getResultSet(Loader.java:2036)
    org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1836)
    org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1815)
    org.hibernate.loader.Loader.doQuery(Loader.java:899)
    org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341)
    org.hibernate.loader.Loader.doList(Loader.java:2522)
    org.hibernate.loader.Loader.doList(Loader.java:2508)
    org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2338)
    org.hibernate.loader.Loader.list(Loader.java:2333)
    org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:490)

Моя база даних:

CREATE TABLE `catalog` (
  `ID_CATALOG` int(11) NOT NULL AUTO_INCREMENT,
  `Catalog_Name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`ID_CATALOG`)
)

CREATE TABLE `product` (
  `id_product` int(11) NOT NULL AUTO_INCREMENT,
  `product_name` varchar(45) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `author` varchar(45) DEFAULT NULL,
  `price` int(11) DEFAULT NULL,
  `catalog_id` int(11) DEFAULT NULL,
  `linkimage` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id_product`),
  KEY `FK_Product_idx` (`catalog_id`),
  CONSTRAINT `FK_Product` FOREIGN KEY (`catalog_id`) REFERENCES `catalog` (`ID_CATALOG`) ON DELETE NO ACTION ON UPDATE NO ACTION
)

Відповіді:


76

В @JoinColumnанотації вказує ім'я стовпця використовується в якості зовнішнього ключа на цільової сутності.

У Productнаведеному вище класі для стовпця приєднання встановлено значення ID_CATALOG.

@ManyToOne
@JoinColumn(name="ID_CATALOG")
private Catalog catalog;

Однак Productвикликається зовнішній ключ на століcatalog_id

`catalog_id` int(11) DEFAULT NULL,

Вам потрібно буде змінити або назву стовпця в таблиці, або ім’я, яке ви використовуєте в @JoinColumnтому, щоб вони збігалися. Див. Http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping-association


27

Ще однією потенційною причиною для інших людей, що стикаються з тим самим повідомленням про помилку, є те, що ця помилка трапиться, якщо ви отримуєте доступ до таблиці в іншій схемі, ніж та, з якою ви автентифікувались.

У цьому випадку вам потрібно буде додати ім’я схеми до запису вашого об’єкта:

@Table(name= "catalog", schema = "targetSchemaName")

це сталося в моєму випадку, коли я спробував створити новий додаток sboot -mysql -jpa. не створено таблиці db. це вирішило моє питання.
Сурадж Патіл

або коли назва таблиці не збігається ... подобається, @Table(name = "catalog", schema = "taretSchemaName")а назва таблиці така taretSchemaName.
Паоло

6

Спробуйте використати внутрішнє приєднання у своєму запиті

    Query query=session.createQuery("from Product as p INNER JOIN p.catalog as c 
    WHERE c.idCatalog= :id and p.productName like :XXX");
    query.setParameter("id", 7);
    query.setParameter("xxx", "%"+abc+"%");
    List list = query.list();

також у конфігураційному файлі сплячого режиму є

<!--hibernate.cfg.xml -->
<property name="show_sql">true</property>

Для відображення запиту на консолі.


5

У мене була та сама проблема, коли я намагався оновити рядок:

@Query(value = "UPDATE data SET value = 'asdf'", nativeQuery = true)
void setValue();

Моя проблема полягала в тому, що я забув додати @Modifyingанотацію:

@Modifying    
@Query(value = "UPDATE data SET value = 'asdf'", nativeQuery = true)
void setValue();

4

У мене була подібна проблема. Спробуйте скористатися редактором HQL. Він відобразить вам SQL (оскільки у вас є виняток з граматики SQL). Скопіюйте свій SQL і виконайте його окремо. У моєму випадку проблема полягала у визначенні схеми. Я визначив схему, але я повинен залишити її порожньою. Це спричинило такий самий виняток, як і ви. І опис помилки відображав фактичний стан, оскільки ім’я схеми було включено до оператора SQL.


4

Якщо у вас у базі даних не створена послідовність 'HIBERNATE_SEQUENCE' (якщо використовується oracle або будь-яка інша база даних), ви отримаєте помилку того ж типу;

Переконайтеся, що послідовність присутня там;


5
Ви могли б детальніше сказати
samisnotinsane

Якщо ви використовуєте Oracle DB і вимкнули створення автоматичної схеми, вам, ймовірно, теж не вистачає послідовності HIBERNATE_SEQUENCE. Якщо це ваш випадок, ви можете спробувати змінити анотацію згенерованого значення на щось інше, наприклад: @GeneratedValue(strategy=GenerationType.IDENTITY)якщо ви часто використовуєте генерацію ідентифікаторів у колонціid NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
Глого

4

Я використав наступні властивості у своєму файлі application.properties, і проблема вирішена

spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl

і

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

раніше отримував помилку

There was an unexpected error (type=Internal Server Error, status=500).
could not extract ResultSet; SQL [n/a]; nested exception is 
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:280)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:254)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

Я припускаю, що це (іноді краща) альтернатива явному коментуванню @Table (name = "каталог", schema = "targetSchemaName"), як пропонувалося вище. Краще, тому що коли ви копіюєте код із програми EE, вам не потрібно змінювати класи сутності.
user2081279

2

З тією ж проблемою я зіткнувся після міграції бази даних з онлайн-сервера на localhost. Схема змінилася, тому мені довелося визначати схему вручну для кожної таблиці:

@Entity
@Table(name = "ESBCORE_DOMAIN", schema = "SYS")

0

Іншим рішенням є додавання @JsonIgnore:

@OneToMany(mappedBy="catalog", fetch = FetchType.LAZY)
@JsonIgnore
private Set<Product> products = new HashSet<Product>(0);

11
Поясніть, як це може вирішити проблему, приятель. Той, хто шукає відповіді, отримав би більше користі від розуміння рішення.
Рай,

0

Я використовував Spring Data JPA з PostgreSql і під час виклику UPDATE він показував помилки -

  • ' не вдалося витягти ResultSet ' та ще один.
  • org.springframework.dao.InvalidDataAccessApiUsageException: Виконання запиту на оновлення / видалення; вкладеним винятком є ​​javax.persistence.TransactionRequiredException: Виконання запиту на оновлення / видалення. ( Відображається обов’язкова транзакція. )

Власне, мені бракувало двох обов’язкових анотацій.

  • @Transactional і
  • @ Модифікація

З-

@Query(vlaue = " UPDATE DB.TABLE SET Col1 = ?1 WHERE id = ?2 ", nativeQuery = true)
void updateCol1(String value, long id);

0

Для MySql пам’ятайте, що писати верблюд - це не дуже добре . Наприклад, якщо схема така:

CREATE TABLE IF NOT EXISTS `task`(
    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `teaching_hours` DECIMAL(5,2) DEFAULT NULL,
    `isActive` BOOLEAN DEFAULT FALSE,
    `is_validated` BOOLEAN DEFAULT FALSE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Ви повинні бути дуже обережними, тому що isActiveстовпець перекладе на isactive. Отже, у вашому класі Entity має бути такий вигляд:

 @Basic
 @Column(name = "isactive", nullable = true)
 public boolean isActive() {
     return isActive;
 }
 public void setActive(boolean active) {
     isActive = active;
 }

Це, принаймні, була моя проблема, яка призвела до вашої помилки

Це не має нічого спільного з MySql, який не враховує регістр, а скоріше є стратегією іменування, яку spring буде використовувати для перекладу ваших таблиць. Докладніше див. У цій публікації

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.