Using VARCHAR or TEXT as default String mapping in OpenJPA - postgresql

By default, OpenJPA's postgres dictionary generates VARCHAR(255) for String fields without stated length. Can it be set up to generate VARCHAR or TEXT instead for all such fields, so that I don't need to repeat #Column(columnDefinition = "TEXT") everywhere? Of course, if the length is given explicitly, e.g. #Column(length = 128), the result should be VARCHAR(128). For that matter, do any other JPA providers allow this?

It seems that Hibernate supports this since 3.6: 6.5. Type Registry. Tracked by this JIRA issue: HHH-5138.

Related

Search on a Numeric Field in a keyword query with Hibernate Search 5

I've tried many ways to search, in a keyword query, for a Long field in my database. I always got errors because Hibernate Search will index the Long as a numeric field. I've tried using FieldBridge, but it just wouldn't work. Here is my field I want to search on.
#Field
#Column(unique = true)
private Long numericField;
I couldn't find anything online on this issue so I'm posting my answer here Q&A-style. I figured a way to do it with a dynamic field, see below:
#Column(unique = true)
private Long numericField;
#Field(name="numericField", analyze = Analyze.NO, index=Index.YES)
public String getNumericFieldAsString(){
return numericField.toString();
}
The field is indexed dynamically as a String now and I can use it in my keyword query.
Keyword queries support long fields just fine: you just have to provide a long value when querying, because the field is of type long. So just use Long.parseLong to turn the text value provided by your user into a long before you pass it to Hibernate Search.
In some cases, you may really need to use a string field for your numeric value. For example if you're targeting multiple fields in the same keyword query, and some of the other fields are string fields.
Then your answer will work fine, though it unfortunately has some side effects that will cause Hibernate Search to reindex data more often (because it doesn't know where getNumbericFieldAsString gets its data from exactly).
Alternatively, you could use bridges, either a custom one, or just this one which is built into Hibernate Search 5:
#Column(unique = true)
#Field(name="numericField", analyze = Analyze.NO, bridge = #FieldBridge(impl = org.hibernate.search.bridge.builtin.LongBridge.class))
private Long numericField;
For information about custom bridges, see here for Hibernate Search 5 and here for Hibernate Search 6 (the newer version of Hibernate Search, with a different API).

PostgreSQL values of column (type text) are shown as numbers

I have a table Campaign_actions which has a column terms with type text.
Today I noticed that all text in the column terms are changed to numbers:
If you use hibernate annotations in java, you need to specify type of Lob. Example:
#Lob
#Type(type = "org.hibernate.type.TextType")
String largeText;

How to specify VARCHAR column length in custom data persister?

I have a custom persister which stores ZonedDateTimes as strings in my database. OrmLite is generating column definition VARCHAR(0) which is invalid in PostgreSQL.
I need to specify a length but I am not sure the best way to do it.
I know I could do something like
#DatabaseField(columnName = "my_column",
persisterClass = MyCustomPersister.class,
columnDefinition = "VARCHAR(17)")
But I would have to do this for every declaration of a field with this datatype. That means that every field annotated with DatabaseField(persisterClass=MyCustomPersister.class) should always be in SQL a VARCHAR of length 17
Is there a way to fix this problem in the data persister?
It is enough with just overriding the method int getDefaultWidth(); in the data persister

Save a java.util.Date in a MySQL DB with Millisecond precision

I would like to get millisecond precision in my MariaDB. After some research, I found that I needed to change the columnDefinition - so I did this in my entity:
#NotNull
#Column(name = "createdDate", columnDefinition = "DATETIME(3) NOT NULL")
#Temporal(TemporalType.TIMESTAMP)
private TimeStamp createdDate;
#PrePersist
void onPersist() {
createdDate = new Timestamp(new Date().getTime());
}
The resulting SQL to create the column is:
`createdDate` DATETIME(3) NOT NULL
Now, in the DB the value has indeed 3 decimals:
2016-09-12 16:57:44.000
... but they are always 000
What did I do wrong, or what did I forget ?
Edit: I tried without JAVA:
CREATE TABLE `test` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`createdDate` DATETIME(3) NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
;
And then:
INSERT INTO test (createdDate)
VALUES(current_timestamp())
Result:
2016-09-13 13:57:44.000
I had the same problem with MariaDB and date types. I've tried org.joda.DateTime and java.util.time types. Both, the server and the client code supported milliseconds correctly.
The problem was that I was using MySQL Connector instead of MariaDB Connector/J JDBC driver.
Background
In most situations using MariaDB with MySQL Connector works out well, but I would never ever recommend this. When I was searching for the issue I was debugging through Hibernate and Connector code and saw many feature detections that were based on the server version number instead of a real feature detection. The version numbering of course differs between MySQL and MariaDB. So there's a big probability that there are far more compatibility issues that are quietly ignored.
Your problem most probably comes from the fact that you mix Dates and Timestamps. Changing the createdDate type to java.sql.Timestamp should solve your issue.
Also, if your version of MySQL is prior to 5.6.4, DateTime won't let you save time fractions.
EDIT after OP's edit :
you are still mixing the Date Java type with Timestamp when you do this :
createdDate = new Timestamp(new Date().getTime());
Can you try createdDate = new Timestamp(System.currentTimeInMilliseconds()); instead ?
Ideally you should use objects from a library like JodaTime to avoid such issues, but that's beyond the point of your question, just a tip :)
Ultimately, if this way of creating your Timestamp does not work, I would use the Timestamp type in DB instead of Datetime, but that's just trial and error as Datetime should work as well in your example.
Edit :
excerpt from Oracle's Date API :
Date()
Allocates a Date object and initializes it so that it represents the time at which it was allocated, measured to the nearest millisecond.
In which case using System.currentTimeInMilliseconds() shouldn't change the outcome - my bad.
To troubleshoot the problem, I'd start to create a date via SQL (without passing via Java objects) with CURRENT_TIMESTAMP to make sure that the field can indeed contain decimal time precision.. If it is OK, verify the value in the Java object with a debugger.. Might give you a lead. If both contain milliseconds, I'd look at the usage of the annotations or start from a working sample.
To do this using pure JPA :
#Column(name="STMP", columnDefinition = "TIMESTAMP (6)")
private Timestamp timestamp = Timestamp.from(Instant.now());

MongoDB generate UUID with dashes

I need to add random UUID with dashes to my column GUID.
How I should write my sql script, I was using GUID = MD5(UUID()); but it generates UUID without dashes, what would be solution ?
If you use MD5(UUID()), it no longer is a UUID, and the "guaranteed unique" property is also lost. Don't do that.
That said, a UUID is a 128 bits number. It doesn't have dashes. Some representations do, but that's a display issue.