Java lang string ошибка

I’m taking a Java class for college, and was working on some given tasks. This is the code I wrote for it.

public class String
{
 public static void main(String[] args)
 {
  String city = "San Francisco";
  int stringLength = city.length();
  char oneChar = city.charAt(0);
  String upperCity = city.toUpperCase();
  String lowerCity = city.toLowerCase();

  System.out.println(city);
  System.out.println(stringLength);
  System.out.println(oneChar);
  System.out.println(upperCity);
  System.out.println();
  }
 }

which yielded these results

C:\Users\sam\Documents\Java>javac String.java
String.java:8: error: incompatible types: java.lang.String cannot be 
converted to String
          String city = "San Franciso";
                        ^
String.java:9: error: cannot find symbol
            int stringLength = city.length();
                                   ^
symbol:   method length()
location: variable city of type String
String.java:10: error: cannot find symbol
            char oneChar = city.charAt(0);
                               ^
symbol:   method charAt(int)
location: variable city of type String
String.java:11: error: cannot find symbol
            String upperCity = city.toUpperCase();
                                   ^
symbol:   method toUpperCase()
location: variable city of type String
String.java:12: error: cannot find symbol
            String lowerCity = city.toLowerCase();
                                   ^
symbol:   method toLowerCase()
location: variable city of type String
5 errors

I’ve tried searching for an answer but I didn’t really find anything that helps. Any help is appreciated, thanks.

asked Jan 26, 2018 at 9:19

2

Since your class is named String, unqualified type reference in String city is taken as reference to your own class.

Either rename the class to some other name, or you’ll have to write java.lang.String wherever you reference the «built-in» Java String class.

answered Jan 26, 2018 at 9:21

Jiri Tousek's user avatar

Jiri TousekJiri Tousek

12.2k5 gold badges29 silver badges44 bronze badges

It is conflict between system class java.lang.String and your class named String. Rename your class String to say MyString, i.e. replace line:

public class String

with

public class MyString

And rename file String.java containing this class to MyString.java.

answered Jan 26, 2018 at 9:37

Anton Tupy's user avatar

Anton TupyAnton Tupy

9515 silver badges16 bronze badges

write one statement java.lang.String.*;
import java.lang.String; your problem will be solved

answered Mar 24 at 11:58

Shubham kumar's user avatar

String is a reserved key word in Java, Please refer to the reserved keywords in java Java Reserved Keywords.

Renaming the class to something other than these keywords would be the solution to your problem. Or you can follow the import statement solution above.

BTW, Please use a good IDE to develop java programs, it seems that your IDE is not showing or linting basic rules.

answered Jun 13 at 20:06

Vijay Krishnamoorthy's user avatar

2

Автор оригинала: Marcos Lopez Gonzalez.

1. введение

Конечно, мы никогда бы не предположили, что мы можем привести String к массиву String в Java:

java.lang.String cannot be cast to [Ljava.lang.String;

Но, оказывается, это распространенная ошибка JPA.

В этом кратком уроке мы покажем, как это происходит и как это решить.

В JPA нередко возникает эта ошибка , когда мы работаем с собственными запросами и используем метод createNativeQuery в EntityManager .

Его Javadoc фактически предупреждает нас , что этот метод вернет список Object [] или просто Object , если запрос возвращает только один столбец.

Давайте рассмотрим пример. Во-первых, давайте создадим исполнителя запросов, который мы хотим повторно использовать для выполнения всех наших запросов:

public class QueryExecutor {
    public static List executeNativeQueryNoCastCheck(String statement, EntityManager em) {
        Query query = em.createNativeQuery(statement);
        return query.getResultList();
    }
}

Как было показано выше, мы используем метод createNativeQuery() и всегда ожидаем результирующий набор, содержащий массив String .

После этого давайте создадим простую сущность для использования в наших примерах:

@Entity
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String text;

    // getters and setters

}

И, наконец, давайте создадим тестовый класс, который вставляет Сообщение перед запуском тестов:

public class SpringCastUnitTest {

    private static EntityManager em;
    private static EntityManagerFactory emFactory;

    @BeforeClass
    public static void setup() {
        emFactory = Persistence.createEntityManagerFactory("jpa-h2");
        em = emFactory.createEntityManager();

        // insert an object into the db
        Message message = new Message();
        message.setText("text");

        EntityTransaction tr = em.getTransaction();
        tr.begin();
        em.persist(message);
        tr.commit();
    }
}

Теперь мы можем использовать наш Исполнитель запросов для выполнения запроса, который извлекает текстовое поле нашей сущности:

@Test(expected = ClassCastException.class)
public void givenExecutorNoCastCheck_whenQueryReturnsOneColumn_thenClassCastThrown() {
    List results = QueryExecutor.executeNativeQueryNoCastCheck("select text from message", em);

    // fails
    for (String[] row : results) {
        // do nothing
    }
}

Как мы видим, поскольку в запросе есть только один столбец, JPA фактически вернет список строк, а не список строковых массивов. Мы получаем ClassCastException , потому что запрос возвращает один столбец, и мы ожидали массив.

3. Ручная Фиксация Литья

Самый простой способ исправить эту ошибку-проверить тип объектов результирующего набора , чтобы избежать исключения ClassCastException. Давайте реализуем метод для этого в нашем Исполнителе запросов :

public static List executeNativeQueryWithCastCheck(String statement, EntityManager em) {
    Query query = em.createNativeQuery(statement);
    List results = query.getResultList();

    if (results.isEmpty()) {
        return new ArrayList<>();
    }

    if (results.get(0) instanceof String) {
        return ((List) results)
          .stream()
          .map(s -> new String[] { s })
          .collect(Collectors.toList());
    } else {
        return (List) results;
    }
}

Затем мы можем использовать этот метод для выполнения нашего запроса без получения исключения:

@Test
public void givenExecutorWithCastCheck_whenQueryReturnsOneColumn_thenNoClassCastThrown() {
    List results = QueryExecutor.executeNativeQueryWithCastCheck("select text from message", em);
    assertEquals("text", results.get(0)[0]);
}

Это не идеальное решение, так как мы должны преобразовать результат в массив, если запрос возвращает только один столбец.

4. Исправление сопоставления сущностей JPA

Другой способ исправить эту ошибку-сопоставить результирующий набор с сущностью. Таким образом, мы можем заранее решить, как сопоставить результаты наших запросов и избежать ненужных отливок.

Давайте добавим еще один метод к нашему исполнителю для поддержки использования пользовательских сопоставлений сущностей:

public static  List executeNativeQueryGeneric(String statement, String mapping, EntityManager em) {
    Query query = em.createNativeQuery(statement, mapping);
    return query.getResultList();
}

После этого давайте создадим пользовательское SqlResultSetMapping для сопоставления результирующего набора нашего предыдущего запроса с Сообщением сущностью:

@SqlResultSetMapping(
  name="textQueryMapping",
  classes={
    @ConstructorResult(
      targetClass=Message.class,
      columns={
        @ColumnResult(name="text")
      }
    )
  }
)
@Entity
public class Message {
    // ...
}

В этом случае мы также должны добавить конструктор, соответствующий нашему недавно созданному SqlResultSetMapping :

public class Message {

    // ... fields and default constructor

    public Message(String text) {
        this.text = text;
    }

    // ... getters and setters

}

Наконец, мы можем использовать наш новый метод исполнителя для выполнения тестового запроса и получения списка Сообщений :

@Test
public void givenExecutorGeneric_whenQueryReturnsOneColumn_thenNoClassCastThrown() {
    List results = QueryExecutor.executeNativeQueryGeneric(
      "select text from message", "textQueryMapping", em);
    assertEquals("text", results.get(0).getText());
}

Это решение намного чище, так как мы делегируем отображение результирующего набора в JPA.

5. Заключение

В этой статье мы показали, что собственные запросы являются общим местом для получения этого ClassCastException . Мы также рассмотрели возможность выполнения проверки типа самостоятельно, а также ее решения путем сопоставления результатов запроса с транспортным объектом.

Как всегда, полный исходный код примеров доступен на GitHub .

What is can not deserialize instance of java.lang.string out of start_object token?

Can not deserialize instance of java.lang.string out of start_object token is a common error message that developers encounter while working with Java applications. It usually occurs when the application attempts to parse JSON data into an object but cannot convert it properly because the input does not conform to the expected format.

To resolve this issue, developers must ensure that the format and structure of their JSON data aligns with what their Java code expects. This may require modifying either or both parts to comply with established standards for proper serialization and deserialization practices.

Common scenarios when encountering Can not deserialize instance of java.lang.string out of start_object token

Deserialization is a critical process in software development that helps convert data from one format to another, such as transforming JSON or XML into objects. However, despite its importance, it can also be prone to errors and exceptions.

One of the most common scenarios developers encounter when deserializing data is the error message “Can not deserialize instance of java.lang.string out of start_object token.” This error message usually indicates an issue with parsing JSON responses, where a string value was expected but instead received an object.

So why does this scenario occur? There are several reasons:

1. Inconsistent Data Format:
When working with APIs or web services which provide inconsistent data formatting during serialization then de-serialization methods like JsonDeserializer won’t work properly and we might come across this error.

2. Mismatched Serialization/Deserialization Mechanisms:
If the serialization process uses different mechanisms than what’s defined in their corresponding Deserializer methods then there could be problems encountered while performing JsonSeriesation operation afterward using Object reader (like GSON) that requires these same mechanisms otherwise developer will get this exception.

3. Corrupted Data:
Another cause for encountering this exception resides on circular references between objects; whereby authors generate instances that do contain recursive loops leading to infinite self-referencing thereby corrupting serialized code.

Now that you understand some possible causes let us dig deeper into how we can approach fixing them.

What Can You Do When Encountering This Error?

There are various strategies available for resolving “Can not deserialize instance of java.lang.string out of start_object token” issues depending on underlying problems(s).

Firstly, check your API specs or documentation – sometimes changing values for incompatible type properties will resolve specific de-serialisation issues As already mentioned previously .

Secondly develop custom adapters: Implementing custom Adapters by creating a class implementing ‘JsonAdapter’. The adapter provides us with full control over how we parse our JSON response down to intellible objects, without dealing with lot of problems related to type mismatched seralisation issues.

Finally, and we strongly suggest this approach as trouble shooting becomes more complex especially if using open source libraries. Consult your documentation provided by the de-serialization library provider on how to debug any underlying issue(s) that maybe leading towards RuntimeExceptions while parsing a JSON response.

In conclusion, while encountering “Can not deserialize instance of java.lang.string out of start_object token” error can cause headaches for developers it is relatively easy to isolate and resolve this Exception. Understanding root cause(s) is key in debugging and finding an adequate solution aimed at resolving the problem efficiently – which can range from changing values specifications or implementing custom Adapters providing us with full control over how we parse our JSON responses down into intellible objects.

Step-by-step guide to fixing Can not deserialize instance of java.lang.string out of start_object token

Have you ever encountered the error message “Can not deserialize instance of java.lang.string out of start_object token”? If so, don’t worry! This error can be easily fixed with a few simple steps. In this guide, we will walk you through how to solve this error and get your program running smoothly again.

Step 1: Understand the Error Message

Before diving into solving the issue, it’s important to understand what the error message is telling you. The phrase “deserialize instance” refers to converting data from a serialized format (such as JSON or XML) back into an object that can be used in code. The rest of the error message is informing us that there’s something wrong when trying to turn a JSON object into a Java string.

Step 2: Check for Syntax Errors

The most common reason for this type of deserialization failure is due to an invalid input format or syntax errors in the JSON document itself. To fix this, open up your JSON file and check if all brackets are properly closed and commas inserted correctly between key-value pairs.

For example:

{
“name”: “John”,
“age”: 30,
}

In this example, there’s an extra comma after age which may cause deserializing issues. By correcting these mistakes priorly could help prevent such problems from occurring further down the lines while parsing

Step 3: Check Java Class Mismatch

Another probable cause for causing such deserialization failures happens when attempting to parse objects whose types do not correspond accurately with their instantiating classes’ expected serialization/deserialization schema. It means if your Java class has defined its variable type as String but json structure coming contains different Schema- then it fails at runtime.

To address this problem: Compare both JAVA model/class properties’ names and datatypes against those inside parsed Json Object; modify any inconsistencies until they match perfectly before reloading onto memory storage space within RAM by updating respective getters/setters methods, so that everything is copacetic.

Step 4: Implement Custom Deserialization

A more advanced solution can be implemented with custom deserializers. By creating a custom deserialize() method you can parse the JSON in your desired way and avoid the default parser’s errors. Here’s how you could do it for our example:

– Create a class extending JsonDeserializer
– Override The “deserialize” Method
– Define this overridden “deserialize” method to implement any logic necessary for parsing input data successfully by reading raw json as string or applying regex pattern to extract specific structure which meets expected format.

Here are some tips if implementing custom deserializer:

1) Use Jackson API – its easier than Gson.

2) Get familiar with docstrings and annotations supporting each of these new features/parameters which come bundled within respective libraries/apis; they will help guide implementations properly avoiding bugs further downstream.

3) Test on sample inputs before integrating final changes over loaded memory space lest outlying cases cause problems up front when running higher loads

By following these steps, you’ll be able to troubleshoot and fix a common issue – Can Not Deserialize Instance Error – preventing downtime or issues within an application quite easily!

Frequently asked questions about Can not deserialize instance of java.lang.string out of start_object token

First off, let’s start with the basics – what does “Can not deserialize instance of java.lang.string out of start_object token” mean?

Essentially, this error message is notifying you that your code was unable to convert a JSON object into a String value. This can occur for various reasons and understanding them is crucial in troubleshooting the issue at hand.

To dive deeper, let’s break down some frequently asked questions regarding this common error:

Q: What causes this error?

A: The main reason why this error typically occurs is because developers try to cast an entire JSON object into a string instead of isolating specific values within it. This creates confusion during serialization as Java does not know which part of the JSON data needs to be converted into a string.

Q: How can I fix it?

A: The solution depends on how precisely you want to handle the situation. One way is by modifying the code so that only strings within the JSON objects are targeted for conversion using methods like getAsString() or getText(). Another option could be identifying when exactly your code expects different data types to receive and handling mismatches accordingly before attempting our desired operation.

In either case, optimizing debug statements will mostly speed up testing timesources show that adequate logging extends development cycle time by just 10-15% while also making errors easier and faster fixes.

Q: Can’t I simply take my existing code and turn it all into Strings?

A: Tempting as this may seem, converting everything towards one type won’t always lead to fruitful results; especially if parsing complex objects through multiple-level nested structures have been necessary beforehand. Instead, parse only selective characteristics whenever feasible instead of transforming anything unnecessarily for swift cross-type operations such as communicating with external services.

Errors related to deserialization may seem intimidating at first glance but having a solid foundation on their causes helps make tackling them much more manageable. Take note that proper optimization techniques such as logging and reliable testing provides critical advantages in identifying where exactly the error lies. As always, a thorough understanding of one’s tools is essential when handling JSON data and related operations; though this can be daunting at times it can prove to be invaluable toward efficient development practices.

Tips and tricks for avoiding Can not deserialize instance of java.lang.string out of start_object token errors

As a developer, there’s nothing more frustrating than seeing the dreaded “Can not deserialize instance of java.lang.string out of start_object token” error message. It can bring development to a standstill – but fear not! With some simple tips and tricks, you can avoid this pesky error and keep your code running smoothly.

Firstly, it’s important to understand what causes this error. Essentially, it occurs when you try to convert JSON data into an object using Java’s Gson library, but the data is not in the correct format. More specifically, Gson expects a string value for a given key, but instead finds an object or array.

With that in mind, here are some ways to prevent this issue:

1. Check your API response

One common cause of this error is receiving unexpected data from an API call. Double-checking the response can help you identify any issues before they become problems further down the line.

2. Use @SerializedName annotations

If you’re working with models that have variable names that don’t match up with your JSON keys (for example: firstName vs first_name), use @SerializedName annotations to specify which key should be matched with each model field.

3. Implement custom serialization/deserialization

In cases where you cannot modify the external API sending malformed JSON objects/arrays encapsulated within fields , implementing custom deserialization/gson adapter classes will read those specific fields as type :java.lang.object Then extract several levels deep(using org.json lib) till we arrive at required String contained inside intruder json oblect/array and assign it correctly thus making sure gson doesn’t choke on such shallow nested mal-formed elements brought about by externally maintained APIs .

4. Don’t mix up types

It may sound obvious, but ensuring that all values being converted are of the expected type will go a long way towards avoiding these errors altogether. Make sure integer values aren’t being interpreted as strings or vice versa!

5. Use a JSON formatter

Last but not least, using a tool like https://jsonformatter.curiousconcept.com/ to format your JSON data before pushing it through Gson can help you identify any syntax errors that may be causing issues.

In conclusion, by following these tips and tricks, you’ll be well-equipped to overcome the “Can not deserialize instance of java.lang.string out of start_object token” error and keep developing with confidence. Happy coding!

Top 5 things you need to know about Can not deserialize instance of java.lang.string out of start_object token

If you’re a programmer or developer, then chances are that at some point you’ve come across the error message “Can not deserialize instance of java.lang.string out of start_object token”. It’s an annoying and cryptic message that can leave even experienced programmers scratching their heads. But don’t worry, we’re here to break it down for you.

Here are the top 5 things you need to know about this pesky error:

1. Deserialization basics
Firstly, let’s start with what serialization and deserialization actually mean. Serialization is the process of converting an object into a stream of bytes so that it can be stored in memory or transferred over a network. Deserialization is the opposite process–converting those bytes back into an object in memory.

2. Start Object Tokens
The problem arises when there is a mismatch between the serialized data and your code attempting to deserialize it back into usable objects from said serialized data. The words “start_object token” refer to JSON syntax where { begins any Json representation of an object – indicating its beginning (like xml tags < being used).

3. Debugging
When parsing JSON within Java based languages like Spring Boot or Jax-RS, Exception messages may indicate one common cause as «can’t parse as enum“. To solve this issue using JAVA, ensure that each value parsed inside JSON matches valid values found within yor Enum(s). Log raw formatted event data prior to trying/reading invalid events.

4. Solution- Override default mapping conventions:
By configuring Jackson ObjectMapper class (within spring boot) via application.properties or environment variable defaults PATH_TO_CHILDREN_SUFFIX: ___childrenPath , BATCH_SIZE : 2000 & TRANSACTION_TYPE_NAME_MAPPER=HelloMapper.class.getSimpleName() Any map keys without configuration shall inherit mapper defaulted parameters if no overriding methods exist.

5.Error Handling Strategies-
Your may consider adopting loose writing habits such as «-» instead of underscore «_»;Or more structured methods including coding Rest Method using POST approach- This will give you more precise control over the data being passed back and forth. Depending on your system requirements, it is also possible to create custom default values for missing or incorrect fields within JSON before serialization, alongside its keys mapped to java object attributes.

In conclusion,
The «Can not deserialize instance of java.lang.string out of start_object token» error message can be a real headache for programmers but understanding its cause improves your ability to code better decoding alghorithms , detecting bad mapping inside class/enum definition in context with received input . By remembering the essentials illustrated herein above such as deserializtion basics which covers think like logical mismatches between serialized and expected deserialized Json there would be no reason why one should encounter this error at all!

Explaining the technical jargon behind Can not deserialize instance of java.lang.string out of start_object token.

If you’re a developer, chances are you’ve come across this error message at some point in your career: “Can not deserialize instance of java.lang.string out of start_object token.” It’s an annoying and cryptic message that can leave many scratching their heads. But fear not! We’re here to shed some light on the technical jargon behind this error.

Firstly, it’s important to understand what serialization is. Serialization essentially means converting an object into a stream of bytes that can be easily transported over a network or saved to disk. Deserialization is the opposite process – taking those bytes and reconstructing the original object.

Now, let’s look at the specific error message: “Can not deserialize instance of java.lang.string out of start_object token.” A Java program encounters this error when it attempts to parse JSON data (which represents objects as key-value pairs) but runs into unexpected data types.

In layman’s terms, think of JSON data as being encapsulated within curly braces {}. Within these braces exist keys and values in ‘key:value’ structure that represent properties like name or age for example; for example:

“`
{
“name”: “Sarah”,
“age”: 26
}
“`

This tells us Sarah’s name is “Sarah” and her age is “26”. However, if we try to serialize complex nested JSON objects where different values may be present under one key-pair value or vice versa can then become tricky.

The problem occurs when trying to convert non-String data types (like integers or arrays) into String format – which would result in breaking apart existing value structures so they no longer adhere strictly with standard conversion methods.. This might happen either due malformed JSON input given Or also limitations built into Standard Library classes could cause such errors occur i.e class type mappings algorithms which works based on limited number assumptions about known types.

So why does this happen? Let’s consider our previous example:

“`
{
“name”: “Sarah”,
“age”: 26,
“hobbies”: [“reading”, “listening to music”],
“address”:{
“street”:”Abbey Road”,
“number”:”13A”,
“city”:”London”
}
}
“`

In this case, when the JSON object is being deserialized into a Java object (presumably with name `Person`), things might run smoothly until it comes across the `”address”` key. What should be assigned here? Should we create another Person nested within our current Person’s records or store simple values like Street as their own attribute /key pair and city in other ? This problem persists since each serialization/deserialization could have different interpretations for handling these edge cases.

To fix this issue, you’ll need to check your input JSON files carefully – make sure that they follow typical data structure practices that standard libraries can work with without divergence. Flexible parsing methods like Gson often provides many customizable settings which allow developers greater control over how data gets translated into objects, thus granting better possibilities working with complex json structures. In general having more standardized approaches helps reduce errors down along line of coding even if early process does feel tedious at times!

Table with useful data:

Error Message Possible Causes Solution
Can not deserialize instance of java.lang.string out of start_object token Incorrect data type configuration Update the data type configuration to match the expected data type

Information from an expert:

This error message typically refers to some issue with the format of JSON object that’s being serialized or deserialized. When trying to deserialize a string token using Jackson, this error can occur if the input data contains an object instead of a string value. Usually, this is caused by improper serialization or deserialization formatting or mismatch between the expected and actual data types. It can be corrected by either fixing the format of JSON objects or updating the code’s type matching logic to align with the correct data types.

Historical fact:

The error message “cannot deserialize instance of java.lang.string out of start_object token” is not a historical fact, but rather a common error encountered in modern-day programming when dealing with JSON data. However, the development and widespread use of JSON can be traced back to its creation by Douglas Crockford in the early 2000s as an alternative lightweight data-interchange format compared to XML.

Walkthrough:

The error message “cannot deserialize instance of java.lang.string out of start_object token” is not a historical fact, but rather a common error encountered in modern-day programming when dealing with JSON data. However, the development and widespread use of JSON can be traced back to its creation by Douglas Crockford in the early 2000s as an alternative lightweight data-interchange format compared to XML.

Walkthrough:

The error message “cannot deserialize instance of java.lang.string out of start_object token” is not a historical fact, but rather a common error encountered in modern-day programming when dealing with JSON data. However, the development and widespread use of JSON can be traced back to its creation by Douglas Crockford in the early 2000s as an alternative lightweight data-interchange format compared to XML.

Исправление ошибки JPA «java.lang.String не может быть приведен к Ljava.lang.String;»

1. Вступление

Конечно, мы никогда не предполагали, что можем преобразоватьString в массивString в Java:

java.lang.String cannot be cast to [Ljava.lang.String;

Но это обычная ошибка JPA.

В этом кратком руководстве мы покажем, как это может возникнуть и как ее решить.

2. Типичная ошибка в JPA

В JPA нередко появляется эта ошибкаwhen we work with native queries and we use the createNativeQuery method of the EntityManager.

ЕгоJavadoc фактически предупреждает нас, чтоthis method will return a list of Object[], or just an Object if only one column is returned by the query.

Давайте посмотрим на пример. Во-первых, давайте создадим исполнителя запросов, который мы хотим повторно использовать для выполнения всех наших запросов:

public class QueryExecutor {
    public static List executeNativeQueryNoCastCheck(String statement, EntityManager em) {
        Query query = em.createNativeQuery(statement);
        return query.getResultList();
    }
}

Как видно выше, мы используем методcreateNativeQuery() и всегда ожидаем, что набор результатов будет содержать массивString.

После этого давайте создадим простую сущность для использования в наших примерах:

@Entity
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String text;

    // getters and setters

}

И, наконец, давайте создадим тестовый класс, который вставляетMessage перед запуском тестов:

public class SpringCastUnitTest {

    private static EntityManager em;
    private static EntityManagerFactory emFactory;

    @BeforeClass
    public static void setup() {
        emFactory = Persistence.createEntityManagerFactory("jpa-h2");
        em = emFactory.createEntityManager();

        // insert an object into the db
        Message message = new Message();
        message.setText("text");

        EntityTransaction tr = em.getTransaction();
        tr.begin();
        em.persist(message);
        tr.commit();
    }
}

Теперь мы можем использовать нашQueryExecutor для выполнения запроса, который извлекает полеtext нашей сущности:

@Test(expected = ClassCastException.class)
public void givenExecutorNoCastCheck_whenQueryReturnsOneColumn_thenClassCastThrown() {
    List results = QueryExecutor.executeNativeQueryNoCastCheck("select text from message", em);

    // fails
    for (String[] row : results) {
        // do nothing
    }
}

Как мы видим,because there is only one column in the query, JPA will actually return a list of strings, not a list of string arrays.  Мы получаемClassCastException, потому что запрос возвращает один столбец, а мы ожидали массив.

3. Исправление ручного литья

The simplest way to fix this error is to check the type of the result set objects, чтобы избежатьClassCastException.. Давайте реализуем метод для этого в нашемQueryExecutor:

public static List executeNativeQueryWithCastCheck(String statement, EntityManager em) {
    Query query = em.createNativeQuery(statement);
    List results = query.getResultList();

    if (results.isEmpty()) {
        return new ArrayList<>();
    }

    if (results.get(0) instanceof String) {
        return ((List) results)
          .stream()
          .map(s -> new String[] { s })
          .collect(Collectors.toList());
    } else {
        return (List) results;
    }
}

Затем мы можем использовать этот метод для выполнения нашего запроса без получения исключения:

@Test
public void givenExecutorWithCastCheck_whenQueryReturnsOneColumn_thenNoClassCastThrown() {
    List results = QueryExecutor.executeNativeQueryWithCastCheck("select text from message", em);
    assertEquals("text", results.get(0)[0]);
}

Это не идеальное решение, поскольку мы должны преобразовать результат в массив, если запрос возвращает только один столбец.

4. Исправление сопоставления сущностей JPA

Another way to fix this error is by mapping the result set to an entity. Таким образом,we can decide how to map the results of our queries in advance и избежать ненужных приведений.

Давайте добавим к нашему исполнителю еще один метод для поддержки использования настраиваемых сопоставлений сущностей:

public static  List executeNativeQueryGeneric(String statement, String mapping, EntityManager em) {
    Query query = em.createNativeQuery(statement, mapping);
    return query.getResultList();
}

После этого давайте создадим настраиваемыйSqlResultSetMapping to, отображающий набор результатов нашего предыдущего запроса на объектMessage:

@SqlResultSetMapping(
  name="textQueryMapping",
  classes={
    @ConstructorResult(
      targetClass=Message.class,
      columns={
        @ColumnResult(name="text")
      }
    )
  }
)
@Entity
public class Message {
    // ...
}

В этом случае мы также должны добавить конструктор, который соответствует нашему вновь созданномуSqlResultSetMapping:

public class Message {

    // ... fields and default constructor

    public Message(String text) {
        this.text = text;
    }

    // ... getters and setters

}

Наконец, мы можем использовать наш новый метод исполнителя для запуска нашего тестового запроса и получения спискаMessage:

@Test
public void givenExecutorGeneric_whenQueryReturnsOneColumn_thenNoClassCastThrown() {
    List results = QueryExecutor.executeNativeQueryGeneric(
      "select text from message", "textQueryMapping", em);
    assertEquals("text", results.get(0).getText());
}

Это решение намного чище, поскольку мы делегируем отображение набора результатов в JPA.

5. Заключение

В этой статье мы показали, что нативные запросы — обычное место для получения этогоClassCastException. Мы также смотрели как на проверку типа, так и на решение проблемы путем сопоставления результатов запроса с транспортным объектом.

Как всегда, доступен полный исходный код примеровover on GitHub.

1. Introduction

Of course, we’d never suppose that we can cast a String to a String array in Java:

java.lang.String cannot be cast to [Ljava.lang.String;

But, this turns out to be a common JPA error.

In this quick tutorial, we’ll show how this comes up and how to solve it.

2. Common Error Case in JPA

In JPA it’s not uncommon to get this error when we work with native queries and we use the createNativeQuery method of the EntityManager.

Its Javadoc actually warns us that this method will return a list of Object[], or just an Object if only one column is returned by the query.

Let’s see an example. First, let’s create a query executor that we want to reuse to execute all of our queries:

public class QueryExecutor {
    public static List<String[]> executeNativeQueryNoCastCheck(String statement, EntityManager em) {
        Query query = em.createNativeQuery(statement);
        return query.getResultList();
    }
}

As seen above, we’re using the createNativeQuery() method and we always expect a result set that contains a String array.

After that, let’s create a simple entity to use in our examples:

@Entity
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String text;

    // getters and setters

}

And finally, let’s create a test class that inserts a Message before running the tests:

public class SpringCastUnitTest {

    private static EntityManager em;
    private static EntityManagerFactory emFactory;

    @BeforeClass
    public static void setup() {
        emFactory = Persistence.createEntityManagerFactory("jpa-h2");
        em = emFactory.createEntityManager();

        // insert an object into the db
        Message message = new Message();
        message.setText("text");

        EntityTransaction tr = em.getTransaction();
        tr.begin();
        em.persist(message);
        tr.commit();
    }
}

Now, we can use our QueryExecutor to execute a query that retrieves the text field of our entity:

@Test(expected = ClassCastException.class)
public void givenExecutorNoCastCheck_whenQueryReturnsOneColumn_thenClassCastThrown() {
    List<String[]> results = QueryExecutor.executeNativeQueryNoCastCheck("select text from message", em);

    // fails
    for (String[] row : results) {
        // do nothing
    }
}

As we can see, because there is only one column in the query, JPA will actually return a list of strings, not a list of string arrays. We get a ClassCastException because the query returns a single column and we were expecting an array.

3. Manual Casting Fix

The simplest way to fix this error is to check the type of the result set objects in order to avoid the ClassCastException. Let’s implement a method to do so in our QueryExecutor:

public static List<String[]> executeNativeQueryWithCastCheck(String statement, EntityManager em) {
    Query query = em.createNativeQuery(statement);
    List results = query.getResultList();

    if (results.isEmpty()) {
        return new ArrayList<>();
    }

    if (results.get(0) instanceof String) {
        return ((List<String>) results)
          .stream()
          .map(s -> new String[] { s })
          .collect(Collectors.toList());
    } else {
        return (List<String[]>) results;
    }
}

Then, we can use this method to execute our query without getting an exception:

@Test
public void givenExecutorWithCastCheck_whenQueryReturnsOneColumn_thenNoClassCastThrown() {
    List<String[]> results = QueryExecutor.executeNativeQueryWithCastCheck("select text from message", em);
    assertEquals("text", results.get(0)[0]);
}

This is not an ideal solution since we have to convert the result to an array in case the query returns only one column.

4. JPA Entity Mapping Fix

Another way to fix this error is by mapping the result set to an entity. This way, we can decide how to map the results of our queries in advance and avoid unnecessary castings.

Let’s add another method to our executor to support the usage of custom entity mappings:

public static <T> List<T> executeNativeQueryGeneric(String statement, String mapping, EntityManager em) {
    Query query = em.createNativeQuery(statement, mapping);
    return query.getResultList();
}

After that, let’s create a custom SqlResultSetMapping to map the result set of our previous query to a Message entity:

@SqlResultSetMapping(
  name="textQueryMapping",
  classes={
    @ConstructorResult(
      targetClass=Message.class,
      columns={
        @ColumnResult(name="text")
      }
    )
  }
)
@Entity
public class Message {
    // ...
}

In this case, we also have to add a constructor that matches our newly created SqlResultSetMapping:

public class Message {

    // ... fields and default constructor

    public Message(String text) {
        this.text = text;
    }

    // ... getters and setters

}

Finally, we can use our new executor method to run our test query and get a list of Message:

@Test
public void givenExecutorGeneric_whenQueryReturnsOneColumn_thenNoClassCastThrown() {
    List<Message> results = QueryExecutor.executeNativeQueryGeneric(
      "select text from message", "textQueryMapping", em);
    assertEquals("text", results.get(0).getText());
}

This solution is much cleaner since we delegate the result set mapping to JPA.

5. Conclusion

In this article, we’ve shown that native queries are a common place to get this ClassCastException. We also looked at doing the type check ourselves as well as solving it by mapping the query results to a transport object.

As always, the full source code of the examples is available over on GitHub.

Понравилась статья? Поделить с друзьями:
  • Java io ioexception ошибка при проверке ключа
  • Java lang securityexception ошибка как исправить на андроид
  • Java lang runtimeexception ошибка андроид
  • Java lang reflect invocationtargetexception ошибка причина
  • Jam inside of machine ошибка