Spring Boot: 2.0.2
Hibernate Core: 5.2.17
dialect: SQLServer2012Dialect
When trying to save entity whose id is a generated GUID into SQL Server
using JpaRepository save() method the operation fails with the following messages:
SQL Error: 8169, SQLState: S0002
Conversion failed when converting from a character string to
uniqueidentifier
HHH000327: Error performing load command :
org.hibernate.exception.SQLGrammarException: could not load an entity
com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed
when converting from a character string to uniqueidentifier
#Id
#GenericGenerator(name = "generator", strategy = "guid", parameters = {})
#GeneratedValue(generator = "generator" , strategy = GenerationType.AUTO)
#Column(name = "ActivityID" , columnDefinition="uniqueidentifier")
private String ActivityID;
Another description of the problem: Conversion failed from a character string to uniqueidentifier
Well, after some digging, here is what solved it for me:
Basically change the mapping to:
private UUID id;
#Id
#GeneratedValue
#Column( columnDefinition = "uuid", updatable = false )
public UUID getId() {
return id;
}
And don't forget to send a (not) friendly email to the DBA that decided to use that id type -.-
Regards
Related
I have a Workers table with column name: "WorkerID"
so I have created entity with #Column(name = "WorkerID").
Whenever I try to use stored procedure that selects WorkerID as ID, it doesn't work. It says The column name WorkerID is not valid.
Is there any annotation I can use to make the both parameters WorkerID and ID not to be mandatory? (so I can use this stored procedure and a simple select on workers table)
The exception given upon executing the query:
com.microsoft.sqlserver.jdbc.SQLServerException: The column name worker_id is not valid.
Failed query:
SELECT Worker_ID AS [ID] From Workers
Working query:
SELECT Worker_ID From Workers
The entity:
#PropertySource("classpath:application.properties")
#Entity
#Table(name = "Workers")
#Data
#NoArgsConstructor
#RequiredArgsConstructor
public class Worker {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Worker_ID")
protected long Worker_ID;
#Column(name = "Email")
private String Email;
#Column(name = "Username")
private String Username;
}
I want to be able to run both queries with the same entity. Is it feasible?
Thanks!
I have spring boot, spring data, hibernate and ms sql,
but with create-drop strategy, hibernate creates table based on older implementation of my #Entity class.
Entity class as so:
#Entity
public class User {
#Id
#GeneratedValue
private int id;
#Column(unique = true, nullable = false)
private String name;
#Column(nullable = false)
private String password;
#Column(nullable = false)
private String email;
#Column(nullable = false)
private boolean active = false;
#Column
private String activationUUID = UUID.randomUUID().toString();
//getters and setters
}
In application.properties, related config:
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.ddl-auto=create-drop
But what I see in stdout, once I run my application:
2018-03-17 12:08:10.973 INFO 876 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.SQLServer2008Dialect
2018-03-17 12:08:11.473 INFO 876 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export
Hibernate: drop table [user]
Hibernate: create table [user] ([id] int identity not null, [account_activationuuid] varchar(255), [account_active] bit not null, [email] varchar(255) not null, [name] varchar(255) not null, [password] varchar(255) not null, [registration_date] datetime2 not null, primary key ([id]))
Hibernate: alter table [user] add constraint UK_gj2fy3dcix7ph7k8684gka40c unique ([name])
2018-03-17 12:08:11.488 INFO 876 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete
Note that I have deleted #Column registration date, renamed accountActivationUUID to activationUUID, and renamed accountActive to active.
Still, I see old schema in stdout, and it is even like this stored in database.
So, my questions:
1) Where does this old schema come from ?
2) Does hibernate have some schema cache ?
3) How to make it generate new schema every time - being exactly representation of #Entity classes in my code ?
4) Why does it say to use 2008 dialect in stdout, even though I have specified 2012 dialect in application.properties ?
I tried invalidating cache in intelj, restarting computer and database, to search for file with old schema definition on hard drive, but none of it worked.
Thanks for any response :)
I found the problem and managed to make it work.
Problem was in pom.xml, there were some duplicates and some non-existent dependencies, so the run was just falling to latest successful run.
That's how it was using old schema.
Can anyone recommend a way to perform inserts in a database table via spring data jpa (in a clustered environment) only when the entry doesn't already exist in the database?
As an example situation, take a database with message and email_address tables. When a new message addressed to 'user#so.com' is added to the message table, a check will be done in the email_address table whether the email 'user#so.com' exists in the email_address and if it doesn't, it gets added to the database. Afterwards the email address entity field is set on the message entity and subsequently the message entity is saved.
#Entity
public class Message {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private EmailAddress emailAddress;
private String content;
}
#Entity
public class EmailAddress {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
// a unique constraint exists on this field on the database
private String email;
}
What should there be done with the spring data jpa EmailAddressRepository to avoid database exceptions that can occur when concurrently trying to insert entities with the same email address?
You could run a check inside a #PrePersist annotated method in your entity. Other than that, I don't think JPA or spring-data provide something out of the box for that.
I've done my first little "hello world" with hibernate, inserting some data in my SQLServer db. Now I'm trying to switch db without change the annotation on my domain classes, and I'm having problems.
I've tried to use a behaviour that let the handling of the id on the db, using an identity column on sql server and a sequence with a trigger on oracle (and i was thinking to do the same with postgres), so i declared in my class
#Id
#Column(name = "ID")
#GeneratedValue(strategy=GenerationType.AUTO)
public long getId() {
return this.id;
}
this work well on SQLServer, but it give me this error on Oracle:
[main] ERROR org.hibernate.util.JDBCExceptionReporter - ORA-02289: sequence does not exist
org.hibernate.exception.SQLGrammarException: could not get next sequence value
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.id.SequenceGenerator.generateHolder(SequenceGenerator.java:132)
at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:105)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:713)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:701)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:697)
at test.Main.main(Main.java:23)
Caused by: java.sql.SQLSyntaxErrorException: ORA-02289: sequence does not exist
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:91)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:206)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:455)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:413)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:1034)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:194)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:791)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:866)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1186)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3387)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3431)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1491)
at org.hibernate.id.SequenceGenerator.generateHolder(SequenceGenerator.java:112)
... 11 more
note that also with strategy=GenerationType.SEQUENCE i got the same error
I was wondering: is there any way to do what i'm trying?
Sorry, i posted the wrong stackTrace, the correct one is:
[main] ERROR org.hibernate.util.JDBCExceptionReporter - ORA-02289: sequence does not exist
org.hibernate.exception.SQLGrammarException: could not get next sequence value
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.id.SequenceGenerator.generateHolder(SequenceGenerator.java:132)
at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:105)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:713)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:701)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:697)
at test.Main.main(Main.java:23)
Caused by: java.sql.SQLSyntaxErrorException: ORA-02289: sequence does not exist
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:91)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:206)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:455)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:413)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:1034)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:194)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:791)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:866)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1186)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3387)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3431)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1491)
at org.hibernate.id.SequenceGenerator.generateHolder(SequenceGenerator.java:112)
... 11 more
note that also with strategy=GenerationType.SEQUENCE i got the same error
It's strange that hibernate is attempting to use IDENTITY generation when you use AUTO. Try using SEQUENCE generation for Oracle9i. Here's an example given in JBoss documentation.
#Entity
#javax.persistence.SequenceGenerator(
name="SEQ_STORE",
sequenceName="my_sequence"
)
public class Store implements Serializable {
private Long id;
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
public Long getId() { return id; }
}
Take a look at this page for documented list of supported generation types on different DB dialects.
I am trying to get a many-to-many relationship working using Grails 2.0.1 on Windows 7. I have exhausted both Google, this site, and my Grails books. Nothing worked. I am connecting to a MS SQL Server 2005 database that I have READ only privileges on and yes - it is a legacy database. Everything in the 2 individual tables works fine (views OK & all) but when I try to add the join table code I get an error:
org.hibernate.HibernateException: Missing table: dbo.IN_USR_DRAWING_PRIV
The table does indeed exist and I can see it fine using IntelliJ's IDEA 10.5 Data Sources view & the MS SQL Server Management Studio. The relevant part of the error is this (I can send more ... much more if needed) :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.HibernateException: Missing table: dbo.IN_USR_DRAWING_PRIV
Here are the 2 domain classes :
class Drawing {
static hasMany = [appusers:Appuser]
String id
String drawingId //this is in the join table
String drawingName
static transients = ['name']
void setName(String name) {
id = name
}
String getName() {
return id
}
static mapping = {
table name: "IN_DRAWING", schema: "dbo"
version false
id column: 'DRAWING_ID', generator:'identity', insertable:false, updateable:false
drawingId column: "`DRAWING_ID`",insertable:false, updateable:false //this is in the join table
drawingName column: "`DRAWING_NAME`"
appusers column: '`USR_ID`',
joinTable: 'IN_USR_DRAWING_PRIV'
}
}
class Appuser {
static belongsTo = Drawing
static hasMany = [drawings:Drawing]
String id
String usrId //this is in the join table
String usrName
static transients = ['name']
void setName(String name) {
id = name
}
String getName() {
return id
}
static mapping = {
table name: 'IN_USR', schema: "dbo"
version false
id column:'USR_ID', generator:'identity', insertable:false, updateable:false //this is in the join table
drawings column: 'DRAWING_ID',
joinTable: 'IN_USR_DRAWING_PRIV'
usrName column: "`USR_NAME`"
}
}
And here is the schema for the join table:
dbo.IN_USR_DRAWER_PRIV
USR_ID (PK, varchar(23), not null)
DRAWING_ID (PK, FK, varchar(23), not null)
PRIV_ID (PK, int, not null)
GRAG reports it has a composite key of all 3 columns, which it does along with a FK on DRAWING_ID.
Solutions that I have tried :
This code (which fails with the "Missing Table" exception.
Adding a domain controller for the join table - same result.
Any hints/clues/solutions appreciated.
I fixed this by using Groovy SQL directly and passing in the T-SQL.