This is probably not an issue. Table and column names in a database form the interface of that database. They are not just an arbitrary implementation detail that's going to be changed at a whim. This is similar to how class and method names in a program are “hardcoded” into calling code. That's not hardcoding, that's just code.
In an object-oriented program, if you expect that the interface of some class you are using might change, then you can implement an anti-corruption layer. This could be an adapter class that specifies a stable interface you want to use, but internally the adapter calls into the unstable, existing interface.
The repository pattern is exactly such an adapter, but for data sources. The repository exposes a convenient database-agnostic interface to your business logic. Internally, the repository might use SQL to load and store data. If the database changes you don't have to change all your code but only the code in the adapter – the change has been concentrated into a small area. Or you could write a completely new adapter. A change might be that you use a completely different database, or maybe that you add a column somewhere – the same concepts apply.
But it is necessary that this adapter or repository knows about the data source it is abstracting over. You could add another abstraction layer between the repository and the data source, but this has diminishing value. At some point, the connection between your code and the table names in the database has to be made. Even if you extract that into a config file, then the config file is effectively code that “hardcodes” these table names.