Annotation for converting boolean to string in OpenJPA - openjpa

Good day!
I read this here that using this annotation below:
import org.apache.openjpa.persistence.ExternalValues;
import org.apache.openjpa.persistence.Type;
#ExternalValues({"true=T", "false=F"})
#Type(String.class)
private boolean sizeWidth;
will enable my JPA to save boolean values from boolean to "T" or "F" on my table. This works beautifully. But now my problem is, what if i have a composite class (embeddable) and it has an boolean as primary key? I used the same approach and declare this annotation to my embeddable but it throws me an error:
Caused by: java.lang.IllegalArgumentException: Can not set boolean field
I know you'll say it is a little bit odd to put boolean as a primary key but it serves its purpose :).
Thanks in advance..

Related

creating Spring JPARepository method for entity variable with name "cId"

I have entity class as
class Policy
{
private String customerId;
private String sicNumber;
private String cId;
/*
more variables can be ignored
*/
}
now inside JPA Repository interface, I want to create method that finds based on sicNumber And cId
following is the attempt i tried
Policy findBySicNumberAndCId(String policyNumber, String cId) ;
above method asks spring to search for "CId" property in entity class
likewise i tried almost all combinations
Policy findBySicNumberAndcId(String policyNumber, String cId) ;
above method caused spring to look for "AndcId".
now the question is what should be the method name that will target right property in entity class.
thanks in advance
The issue is with the way Spring Data JPA forms the query out of the method name. It follows the regular camel casing approach where the field names are inferred. As per the convention followed, if a method name has uppercase letters consecutively, the field name is inferred in uppercase.
So in your case, findBySicNumberAndCId - the field inferred is CId & is failing to find it.
One way to overcome the problem is having the method name with CId in the beginning with 'c' being in lowercase i.e., findBycIdAndSicNumber .
Alternatively, you can consider renaming the variable to avoid these issues or make use of #Query & define your queries if renaming the variables is not possible.
More info about the issue :
https://github.com/spring-projects/spring-data-commons/issues/1996

Could not determine type for: java.util.Map: JPA2 Map annotation

I use JPA in standalone mode. I have this error when i launch the persistenceManager:
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
I have test several work around grabbed around the net... no success.
Can you give me some clues ?
Could not determine type for: java.util.Map..................
for columns: [org.hibernate.mapping.Column(initRegisters)]
I have configured my mapping like this:
#ElementCollection(targetClass = Integer.class)
#MapKeyClass(InitRegister.class)
private Map<Integer, InitRegister> initRegisters = new HashMap<>();
What am i doing wrong ?
Thx in advance !
targetClass attribute of ElementCollection when applied to a map, refers to the type of the Map value - in your case, this is the InitRegister
On the other hand, #MapKeyClass refers to the type of the Map key, which is an Integer type.
So to fix your mistake, you just switch the types:
#ElementCollection(targetClass = InitRegister.class)
#MapKeyClass(Integer.class)
private Map<Integer, InitRegister> initRegisters;
You need not specify the targetClass and MapKeyClass if you are using generics.
So this one should be fine as well:
#ElementCollection
private Map<Integer, InitRegister> initRegisters;
Also, keep in mind that #ElementCollection is used only for basic types and embeddable types. If your InitRegister class happens to be an entity type, then you should not use #ElementCollection. You should use collection valued relationship mappings, either #OneToMany or #ManyToMany.
Solution Found:
Actually, all change was done on the declaration. I tried to add annotation on the getters field and..... it works.
Don't know why. I know that is a good practice but not mandatory.
Prob solved.

Way to enforce length check constraint in MyBatis

I have some check constraints defined by SYS schema in DB for a particular column.
Now, while invoking it from Java code through MyBatis, is there anyway to enforce corresponding field length validations through MYBatis configuration only.
PS: I don't want to enforce constraints at VO level (setter individually). Or using JSR 303
DataBase : Oracle 11g
Using MyBatis
If you do not want to validate in your java beans (manually, or using JSR 303) I think you could write your own typeHandler for those field.
Typehandler would handle String fields and do validation.
See code example for String TypeHandler.
You could enforce your validation logic (of any complexity) in handler's get/set methods.
If you want to use TypeHandler to trim string to given length when saving to database, do it in setNonNullParameter method.
Sample code below
#MappedJdbcTypes(JdbcType.VARCHAR)
public class ExampleTypeHandler extends BaseTypeHandler<String> {
#Override
public void setNonNullParameter(PreparedStatement ps, int i,
String parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, parameter.substring(0,DESIRED_MAX_LENGTH));
}
You could also trim (or otherwise modify) values you read from database- you need to modify get* method in your TypeHandler implementation to do that.
You must tell mappers to use your handler. Otherwise, default handler for given type will be used.
Your SQLs in XML file must use syntax
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
Check https://mybatis.github.io/mybatis-3/sqlmap-xml.html for details.

Spring Data JPA repository methods don't recognize property names with underscores

I have underscores in the entity property names, and when Spring tries to create the JPA repository implementation, it results in an exception trying to resolve the name of the property.
Entity:
#Entity
public class Student {
#Id
private String s_id;
private String s_name;
...
}
Repository:
#Repository
#Transactional
public interface StudentRepository extends CrudRepository<Student, String> {
List<Student> findByS__name(String name);
}
Exception:
org.springframework.data.mapping.PropertyReferenceException:
No property s found for type Student
It is said here http://docs.spring.io/spring-data/jpa/docs/current/reference/html/
If your property names contain underscores (e.g. first_name) you can
escape the underscore in the method name with a second underscore. For
a first_name property the query method would have to be named
findByFirst__name(…).
I just did as document said, but I still got the exception.
I dont want write #Query by myself, and I need underscore in my property name, how to fix this problem?
I use Spring data jpa 1.8.0.RELEASE + hibernate 4.3.9.Final
Avoid using underscores in the entity property names if you have control over the property naming. This will resolve your repository woes, and will result in a cleaner code-base. Developers dealing with the code after you will thank you.
Note, it's not just my opinion: Spring specifically discourages using underscores.
As we treat underscore as a reserved character we strongly advise to
follow standard Java naming conventions (i.e. not using underscores in
property names but camel case instead).
this JIRA issue shows why the documentation was updated with this reccomendation, and the part describing the double underscore option were removed.
I suspect your root problem is that Spring/Hibernate is not mapping camel case property names to the snake case names you have for your columns in the database. What you really need is for your property name to be interpreted in the SQL that hiberate generates as S_NAME.
Is that why underscores in your property name are "required"? If so, there are a few solutions:
Option 1: #Column annotation
To get JPA/Hibernate to map to the correct column names you can tell it the names explicitly. Use the annotation #Column(name="...") to tell it what column names to use in SQL. Then the field names are not constrained by the column names.
#Entity
public class Student {
#Id
#Column(name="s_id")
private String sId;
#Column(name="s_name")
private String sName;
//...getters and setters...
}
Option 2: Improved Naming Strategy
Or if your application has a large number of entities, rather than adding #Column to every property, change the default naming strategy in your configuration file to the hibernate improved naming strategy.
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
This naming strategy will convert camelCase to SNAKE_CASE. Then your class could look as simple as this:
#Entity
public class Student {
#Id
private String sId;
private String sName;
//...getters and setters...
}
Using either of those options, when it creates the SQL it will resolve the column names to:
S_ID
S_NAME
Note: If you are using, or can use Spring Boot, the auto-configuration default will use SpringNamingStrategy, which is a slightly modified version of the hibernate improved strategy. You won't have to do anything to get this improved naming strategy.
The finish line:
Using camel case in your property names you can write your repository method name using camel case, and you can stop trying to wrangle the double underscore:
#Repository
#Transactional
public interface StudentRepository extends CrudRepository<Student, String> {
List<Student> findBySName(String name);
}
Writing double underscore i.e. writing findByS__Name() for property name s_name just does not work. I have tried and tested it. Go by the above answer and change the name of existing instance variables in your entity class. Just dont change getters and setters as they might be used in the existing code.
If you cant change the entities which was my case then better use jqpl query or native sql query on top of repository method
#Query("select s from Student s where s.s_name=?")
List<Student> findBySName();

JPA validation problem: Entity 'X' has no Id or EmbeddedId

Which, I couldn't quite figure out why Eclipse Galileo's JPA validator would say so, as my class 'X' clearly had an #Id annotation on the primary key "uniqueId". The error would disappear if I commented out the #Basic annotation line, but that didn't quite make sense. Anyway, attaching snippet below from memory:
#Entity
class X {
...
#Id
#Basic(optional=false)
#Column(name="someUniqueId", unique=false)
String uniqueId;
...
}
Is this a bug, or is there a JPA standard which I'm not aware of on the use of annotations?
You have here a similar case which may suggest a case or type issue.
But as mentioned here, I would rather bet on bug 217192 (which can be comared with the "non-bug" 208249)
You can also specify which version of eclipse and Dali JPA Tool you are using.
#EmbeddedId
String uniqueId;
You annotated the "uniqueId" with "unique=false".
This could be the root because IDs have to be unique.
You do not need a #Basic annotation as #Id already restricts the attribute's type (as defined by the spec) and the only information #Basic can add are settings for fetch and optional both of which make no sense for a primary key (i.e. a primary key must have fetch=EAGER and optional=false).