Spring JPA postgres ltree extension - postgresql

I have created my entity with one of the column type as Ltree following the article
public class Aor implements Serializable {
private static final long serialVersionUID = 4L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private Long id;
#Column(unique = true, nullable = false, columnDefinition="ltree")
#Type(type = "com.ge.ec.authz.util.LTreeType") //Convert Varchar type to ltree type
private String name;
private String description;
private String shortName;
#JsonIgnore
private int level;
private boolean lowest;
To test Junits I'm trying to use postgres mode as h2 database, I have added below line in application.properties file
spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE;DEFAULT_NULL_ORDERING=HIGH;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:init.sql'
In init.sql I have added below command to create ltree extension
CREATE EXTENSION IF NOT EXISTS LTREE WITH SCHEMA public;
When I try to execute the junits I'm getting below error. Appreciate any help
Syntax error in SQL statement "CREATE [*]EXTENSION IF NOT EXISTS LTREE WITH SCHEMA public"; expected "OR, FORCE

Related

unable to get table from postgreSQL despite the spring boot program being connected to database and the database not being empty

I am rather new to Spring boot and I am trying to write a very simple program that can perform post, get and delete on a postgreSQL data base. the database is named "recipes" schema "public" and table "recipe"
The problem that I ran into is that when I make the get request through postman, it simply returns null despite the data base being initialized with data.
like so
I did my best to try and narrow down the problem and the furthest I got is that line from the service layer is returning nothing when evaluated
jdbcTemplate.query(sql, new RecipeRowMapper())
The database is initialized with the following SQL
INSERT INTO recipe(id, name, ingredients, instructions, date_added)
values (1, 'ini test1', '10 cows 20 rabbits', 'cook ingredients with salt', '2004-01-02'),
(2, 'ini test2', '30 apples 20 pears', 'peel then boil', '2004-01-13');
I know the database is not empty because when I run the following SQL
SELECT * from recipe
i get
And the data base is connected as seen below (one thing I do find strange is that the table "recipe" isn't showing up in the DB browser but I don't know what to make of it)
application.yml
app:
datasource:
main:
driver-class-name: org.postgresql.Driver
jdbc-url: jdbc:postgresql://localhost:5432/recipes?currentSchema=public
username: postgres
password: password
server:
error:
include-binding-errors: always
include-message: always
spring.jpa:
database: POSTGRESQL
hibernate.ddl-auto: create
show-sql: true
dialect: org.hibernate.dialect.PostgreSQL9Dialect
format_sql: true
spring.flyway:
baseline-on-migrate: true
this is the service layer
public List<Recipe> getRecipes(){
var sql = """
SELECT id, name, ingredients, instructions, date_added
FROM public.recipe
LIMIT 50
""";
return jdbcTemplate.query(sql, new RecipeRowMapper());
}
and this is the controller
#GetMapping(path = "/test")
public String testRecipe(){
return recipeService.test();
}
and rowmapper
public class RecipeRowMapper implements RowMapper<Recipe> {
#Override
public Recipe mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Recipe(
rs.getLong("id"),
rs.getString("name"),
rs.getString("ingredients"),
rs.getString("instructions"),
LocalDate.parse(rs.getString("date_added"))
);
}
}
finally recipe entity looks like this
#Data
#Entity
#Table
public class Recipe {
#Id
#GeneratedValue(
strategy = GenerationType.IDENTITY
)
#Column(name = "id", updatable = false, nullable = false)
private long id;
#Column(name = "name")
private String name;
#Column(name = "ingredients")
private String ingredients;
#Column(name = "instructions")
private String instructions;
#Column(name = "date_added")
private LocalDate dateAdded;
public Recipe(){};
public Recipe(long id, String name, String ingredients, String instructions, LocalDate date){}
public Recipe(String name,
String ingredients,
String instructions,
LocalDate dateAdded
) {
this.name = name;
this.ingredients = ingredients;
this.instructions = instructions;
this.dateAdded = dateAdded;
}
}
As it turns out the problem is caused by the LocalDate not being converted correctly and was being posted as null. That caused the
LocalDate.parse(rs.getString("date_added"))
to throw a null pointer exception which is what has been causing all the problems...

Encountering PSQLException when trying to get entry from Postgres database

I have an entity class below. As an important that, user_config column keeps JSON based user configuration so that I had to annotate the variable with #Lob.
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "user_name")
#NotNull
private String userName;
#Lob
#Column(name = "user_config")
#NotNull
private String userConfig;
I am trying to get a bunch of entries over the JPA repository from the database below:
#Repository
public interface UserConfigRepository extends CrudRepository<UserConfig, Long> {
List<UserConfig> findByUserName(String userName);
}
Finally, I have an exception below:
Caused by: org.postgresql.util.PSQLException: Bad value for type long : "some user info"
at org.postgresql.jdbc.PgResultSet.toLong(PgResultSet.java:2894)
at org.postgresql.jdbc.PgResultSet.getLong(PgResultSet.java:2101)
at org.postgresql.jdbc.PgResultSet.getClob(PgResultSet.java:447)
at org.postgresql.jdbc.PgResultSet.getClob(PgResultSet.java:434)
at com.zaxxer.hikari.pool.HikariProxyResultSet.getClob(HikariProxyResultSet.java)
at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$1.doExtract(ClobTypeDescriptor.java:44)
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:243)
at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:329)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:3087)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1877)
at org.hibernate.loader.Loader.hydrateEntityState(Loader.java:1805)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1778)
at org.hibernate.loader.Loader.getRow(Loader.java:1626)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:743)
at org.hibernate.loader.Loader.getRowsFromResultSet(Loader.java:1042)
at org.hibernate.loader.Loader.processResultSet(Loader.java:993)
at org.hibernate.loader.Loader.doQuery(Loader.java:962)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:352)
at org.hibernate.loader.Loader.doList(Loader.java:2857)
... 102 more
Could you please assist me to fix this error?
PS:SpringBoot Version:2.3.2.RELEASE

JPA repository retrieve custom primary key value after save

I have an entity class pointing to postgresql table. Below is table structure. The paymentreferencenumber is the PK which is populated by a trigger. id field is the sequence generated field. When i try to save in this table using JPARepository save method it inserts the first record. But after that it fails due to the primary key constraint. Since PK is a string type and generated using trigger I am specifying generator strategy as 'select'. Can anyone help me with this blocker and point me in the right direction. Thanks
Table structure --
custId serial not null,
paymentreferencenumber varchar(32) not null
constraint customers1_pkey
primary key,
firstname varchar(255),
lastname varchar(255)
Entity class --
#Entity
#Table(name = "customersnew")
public class Customer implements Serializable {
private static final long serialVersionUID = -1L;
#GeneratedValue(generator = "seq")
#GenericGenerator(name="seq", strategy="sequence", parameters = { #Parameter(name="key", value = "customersnew_custid_seq")})
#Column(name = "custid")
private long id;
#Id
#GeneratedValue(generator = "trigger_generated")
#GenericGenerator(name="trigger_generated", strategy="select", parameters = { #Parameter(name="key", value = "id")})
#Column(name = "paymentreferencenumber")
private String refNum;
#Column(name = "firstname")
private String firstName;
#Column(name = "lastname")
private String lastName;
}
--- Controller using JPA save
#RestController
public class CustomerController {
#Autowired
CustomerRepository repository;
EntityManagerFactory emf;
public CustomerController(CustomerRepository repository, EntityManagerFactory emf) {
this.repository = repository;
this.emf = emf;
}
#PostMapping("/create")
public String create(#RequestBody CustomerUI customer){
// save a single Customer
Customer returnObj = repository.saveAndFlush(new Customer(customer.getFirstName(), customer.getLastName()));
PersistenceUnitUtil util = emf.getPersistenceUnitUtil();
Object retObj = util.getIdentifier(returnObj);
return "Customer is created";
}
If you don't specify an id generation strategy, Hibernate will use GenerationType.AUTO. This will result in any of
AUTO - either identity column, sequence or table depending on the
underlying DB.
If you look here, you'll notice all of those generate ids of type long, short or int, not of type String.
Say you wanted a String UUID as an id, you could use
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid2")
#Column(name = "paymentreferencenumber")
private String refNum;

Hibernate #Column annotation cannot mapping to database

I have a Entity in Spring Boot and PostgreSql, I'm using #Column annotation to mapping to database. This is my Entity snip code :
#Entity(name = "users")
#Table(name = "users", schema = "public")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 12355345L;
#Id
#Column(name = "user_id")
private String userid;
#Column(name = "user_name")
private Integer username;
When id run and test with postman, i get an error :
org.springframework.dao.InvalidDataAccessResourceUsageException: could
not extract ResultSet; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not extract
ResultSet
Caused by: org.postgresql.util.PSQLException: ERROR: column users0_.usersid does not exist
Hint: Perhaps you meant to reference the column "users0_.user_id".
I don't know why. How to resolve this ?
There are couple of things for your info.
1) Need to check your spring.jpa.hibernate.ddl-auto property as depends on that property, the database tables, columns will be populated by Hibernate.
2) Next drop the existing table and change the value as spring.jpa.hibernate.hbm2ddl.auto=update so that it will create/update table according to the annotations provided in the entity class
3) Remove unnecessary annotations. Following is enough.
#Entity
#Table(name = "users")
public class User implements Serializable {
#Id
#Column(name = "user_id")
private String userid;
................

Spring data jpa JOIN does't work in #Query

I am using spring-data-jpa. I wrote a native query but it doesn't work. Here is my entity classes:
#Entity
#Table(name="view_version")
public class ViewVersionDom {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name="view_id")
private ViewDom view;
private Integer version;
#ManyToOne
#JoinColumn(name="datasource_param_id")
private DatasourceParamDom datasourceParam;
private String description;
#Column(name="created_date")
private Date createdDate;
#Entity
#Table(name="view_permission")
public class ViewPermissionDom extends BaseDom {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name="view_id")
private ViewDom view;
#ManyToOne
#JoinColumn(name="user_id")
private UserDom user;
#ManyToOne
#JoinColumn(name="group_id")
private GroupDom group;
private Boolean read;
private Boolean write;
private Boolean execute;
Here is the query:
#Query(value = " SELECT v FROM ViewVersionDom v LEFT JOIN ViewPermissionDom vp ON v.view.id = vp.id "
+ " where (v.view.user.id = ?1 OR (vp.read=true and (vp.user.id=?1 or vp.user.id is NULL and vp.group.id is NULL or vp.group.id in (?2)))) "
+ " ORDER BY v.view.name", nativeQuery=true)
public List<ViewVersionDom> findUserViews(Long userId, List<Long> groupIds);
At first when I didn't write nativeQuery=true the application didn't build and I got an exception 'path expected for join jpa'. When I set the settings nativeQuery=true the application is started, but when I call the function I got the following error:
org.hibernate.engine.jdbc.spi.SqlExceptionHelper - [ERROR: relation "viewversiondom" does not exist Position: 16]
org.hibernate.exception.SQLGrammarException: could not extract ResultSet]
Does there any other settings or annotation that will resolve the problem?
I have searched in google, but in all cases 2 tables connected with each other directly.
Your query is not a SQL query (assuming, you don't have a column v in one for your tables).
Also the Table viewversiondom doesn't exist or is not accessible to the database user used for the connection.
Also when mapping native queries to domain objects you should have a look at https://jira.spring.io/browse/DATAJPA-980