How to store byte[] in ORMLite Android? - ormlite

This may be a duplicate question but none of the previous answer could work for me.
I am trying to store the byte[] in ormlite but I am getting following error.
java.sql.SQLException: ORMLite does not know how to store class [B for field 'imageBytes'. byte[] fields must specify dataType=DataType.BYTE_ARRAY or SERIALIZABLE
I am have already added field type as dataType=DataType.BYTE_ARRAY in java class and in config file also.
Here is my Java class.
public class ImageData {
#DatabaseField
private long id;
#DatabaseField(dataType = DataType.BYTE_ARRAY)
byte[] imageBytes;
public ImageData() {
}
public ImageData(long id, byte[] imageBytes) {
this.id = id;
this.imageBytes = imageBytes;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public byte[] getImageBytes() {
return imageBytes;
}
public void setImageBytes(byte[] imageBytes) {
this.imageBytes = imageBytes;
}
public void saveImage(DatabaseHelper dbHelper) throws java.sql.SQLException{
Dao<ImageData,Long> dao = dbHelper.getImageDataDao();
dao.createOrUpdate(this);
}
public static ImageData getImage(DatabaseHelper dbHelper,long id)throws java.sql.SQLException{
Dao<ImageData,Long> dao = dbHelper.getImageDataDao();
ImageData obj = dao.queryForId(id);
return obj;
}
}
And here is my ormlite_config.txt file contents.
# --table-start--
dataClass=com.sample.model.ImageData
tableName=imageData
# --table-fields-start--
# --field-start--
fieldName=id
generatedId=true
allowGeneratedIdInsert=true
# --field-end--
# --field-start--
fieldName=imageBytes
dataPersister = DataType.BYTE_ARRAY
# --field-end--
# --table-fields-end--
# --table-end--
I used dataPersister as suggested in this answer. Instead of dataPersister I have tried dataType also in my config file. I am not able find the solution. Whats the problem with my code?

I used dataPersister as suggested in this answer. Instead of dataPersister I have tried dataType also in my config file.
That answer specifically says that you should use dataPersister = BYTE_ARRAY not DataType.BYTE_ARRAY. Did you try that?

Related

Spring-Boot RestController: Passing Id as String not working

I connected my Spring-Boot-Application to a MongoDB. The application is nothing serious, just for getting into working with spring and MongoDB.
The problem it, that my id is a String and I get an Internal Server Error, when I pass the id of a database entry, in order to get it byId...
This is my domain class:
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
#Document(collection = "songinfo")
public class SongInfo {
#Id
private String id;
private int songId;
private String songName;
private String description;
}
The Controller-Method:
#RequiredArgsConstructor
#RestController
#RequestMapping("/songsinfo")
public class SongsInfoController {
private final SongInfoService songInfoService;
#GetMapping(value = "/{id}", headers = "Accept=application/json", produces =
{MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<SongInfo> getSongInfoById(#PathVariable(value = "id") String id) {
SongInfo songInfo = songInfoService.getSongInfoById(id);
if (songInfo == null)
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(songInfo, HttpStatus.OK);
}
The SongInfoServiceImpl:*
#Override
public SongInfo getSongInfoById(String id) {
return songInfoRepository.findById(id).orElseThrow(NotFoundException::new);
}
This is the SongsInfoRepository:
public interface SongInfoRepository extends MongoRepository<SongInfo, String> {
}
Getting all songinfos from the database is working fine:
But when is pass the id from one of these entries, I get this:
What is wrong here with my implementation?
You're throwing the exception in SongInfoServiceImpl which is not handled in your SongsInfoController Class.
Solution 1: Instead of throwing the exception return null.
SongInfoServiceImpl.java
#Override
public SongInfo getSongInfoById(String id) {
return songInfoRepository.findById(id).orElse(null);
}
Solution 2: Add try catch block
SongsInfoController.java
#RequiredArgsConstructor
#RestController
#RequestMapping("/songsinfo")
public class SongsInfoController {
private final SongInfoService songInfoService;
#GetMapping(value = "/{id}",
headers = "Accept=application/json",
produces = {MediaType.APPLICATION_JSON_VALUE}
)
public ResponseEntity<SongInfo> getSongInfoById(#PathVariable(value = "id") String id) {
SongInfo songInfo = null;
try {
songInfo = songInfoService.getSongInfoById(id);
} catch(Exception e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(songInfo, HttpStatus.OK);
}
}
I think you need to divide two problem.
Check id parameter SongsInfoController
Inside controller check your parameter is valid through log or sysout
Check getSongInfoById method in SongInfoServiceImpl
Simply getSongInfoById(8752); is get error?
I want to add comment but my reputation is under 50.
If you comment above two solution check result, then I will add additional answer.

Rest API with Spring Data MongoDB - Repository method not working

I am reading and learning Spring Boot data with MongoDB. I have about 10 records in my database in the following format:
{
"_id" : ObjectId("5910c7fed6df5322243c36cd"),
name: "car"
}
When I open the url:
http://localhost:8090/items
I get an exhaustive list of all items. However, I want to use the methods of MongoRepository such as findById, count etc. When I use them as such:
http://localhost:8090/items/count
http://localhost:8090/items/findById/5910c7fed6df5322243c36cd
http://localhost:8090/items/findById?id=5910c7fed6df5322243c36cd
I get a 404.
My setup is as so:
#SpringBootApplication
public class Application {
public static void main(String[] args) throws IOException {
SpringApplication.run(Application.class, args);
}
}
#Document
public class Item implements Serializable {
private static final long serialVersionUID = -4343106526681673638L;
#Id
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#RepositoryRestResource(collectionResourceRel = "item", path = "items")
public interface ItemRepository<T, ID extends Serializable> extends MongoRepository<Item, String>, ItemRepositoryCustom {
}
What am I doing wrong? Do I need to implement the methods as defined by MongoRepository or will they be automatically implemented? I am lost and have been trying to figure this out for so long. I do not have any methods in my controller, its empty.
You have to declare the findById method in order for it to be exposed.
Item findById(String id);
Item findByName(String name);
Note that you don't need to implement the methods. SpringBoot will analyse the method name and provide the proper implementation
I had same issue,
After removing #Configuration,#ComponentScan everything worked fine.

JPA2.0 property access in spring rest data -- some getters not being called

I am still somewhat of a novice with Spring Boot and Spring Data Rest and hope someone out there with experience in Accessing by Property. Since I cannot change a database which stores types for Letters in an unnormalized fashion (delimited string in a varchar), I thought that I could leverage some logic in properties to overcome this. However I notice that when using property access, some of my getters are never called.
My Model code:
package ...
import ...
#Entity
#Table(name="letters", catalog="clovisdb")
#Access(AccessType.PROPERTY)
public class Letter {
public enum PhoneticType {
VOWEL, SHORT, LONG, COMMON;
public static boolean contains(String s) { ... }
}
public enum PositionType {
ALL, INITIAL, MEDIAL, FINAL;
public static boolean contains(String s) { ... }
}
public enum CaseType {
ALL, LOWER, UPPER;
public static boolean contains(String s) { ... }
}
private int id;
private String name;
private String translit;
private String present;
private List<PhoneticType> phoneticTypes;
private CaseType caseType;
private PositionType positionType;
#Id
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getTranslit() { return translit; }
public void setTranslit(String translit) { this.translit = translit; }
public String getPresent() { return present; }
public void setPresent(String present) { this.present = present; }
public String getTypes() {
StringBuilder sb = new StringBuilder(); //
if (phoneticTypes!=null) for (PhoneticType type : phoneticTypes) sb.append(" ").append(type.name());
if (caseType!=null) sb.append(" ").append(caseType.name());
if (positionType!=null) sb.append(" ").append(positionType.name());
return sb.substring( sb.length()>0?1:0 );
}
public void setTypes(String types) {
List<PhoneticType> phoneticTypes = new ArrayList<PhoneticType>();
CaseType caseType = null;
PositionType positionType = null;
for (String val : Arrays.asList(types.split(" "))) {
String canonicalVal = val.toUpperCase();
if (PhoneticType.contains(canonicalVal)) phoneticTypes.add(PhoneticType.valueOf(canonicalVal));
else if (CaseType.contains(canonicalVal)) caseType = CaseType.valueOf(canonicalVal);
else if (PositionType.contains(canonicalVal)) positionType = PositionType.valueOf(canonicalVal);
}
this.phoneticTypes = phoneticTypes;
this.caseType = (caseType==null)? CaseType.ALL : caseType;
this.positionType = (positionType==null)? PositionType.ALL : positionType;
}
#Override
public String toString() { .... }
}
My Repository/DAO code:
package ...
import ...
#RepositoryRestResource
public interface LetterRepository extends CrudRepository<Letter, Integer> {
List<Letter> findByTypesLike(#Param("types") String types);
}
Hitting this URI: http://mytestserver.com:8080/greekLetters/6
and setting breakpoints on all the getters and setters, I can see that the properties are called in this order:
setId
setName
setPresent
setTranslit
setTypes
(getId not called)
getName
getTranslit
getPresent
(getTypes not called !!)
The json returned for the URI above reflects all the getters called, and there are no errors
{
"name" : "alpha",
"translit" : "`A/",
"present" : "Ἄ",
"_links" : {
"self" : {
"href" : "http://mytestserver.com:8080/letters/6"
}
}
}
But why is my getTypes() not being called and my JSON object missing the “types” attribute? I note that the setter is called, which makes it even stranger to me.
Any help would be appreciated!
Thanks in advance
That's probably because you don't have a field types, so getTypes() isn't a proper getter. Try adding this to your entity
#Transient
private String types;
I don't know how the inner works, but it's possible that the class is first scanned for its fields, and then a getter is called for each field. And since you don't have types field, the getter isn't called. Setter getting called could be a feature but I wouldn't be surprised if it is a bug, because findByTypesLike should translate to find Letters whose types field is like <parameter>, and types is not a field.
Another thing you can try, is to annotate that getter with #JsonInclude. Jackson 2 annotations are supported in Spring versions 3.2+ (also backported to 3.1.2).

How to implement LeafValueEditor<Address>

I am trying to understand how to correctly implement a LeafValueEditor for a non immutable object. Which of the two way is correct, or should something else be used?
public class Address {
public String line1;
public String city;
public String zip;
}
Option 1:
public class AddressEditor implements LeafValueEditor<Address>
{
private String line1;
private String city;
private String zip;
private Address address;
public void setValue(Address value)
{
this.line1 = value.line1;
this.city = value.city;
this.zip = value.zip;
this.address = value;
}
public Address getValue()
{
this.address.line1 = this.line1;
this.address.city = this.city;
this.address.zip = this.zip;
return this.address;
}
}
Option 2:
public class AddressEditor implements LeafValueEditor<Address>
{
private String line1;
private String city;
private String zip;
public void setValue(Address value)
{
this.line1 = value.line1;
this.city = value.city;
this.zip = value.zip;
}
public Address getValue()
{
Address a = new Address();
this.a.line1 = this.line1;
this.a.city = this.city;
this.a.zip = this.zip;
return a;
}
}
Probably neither, though both technically could work.
A LeafValueEditor is an Editor for leaf values - that is, values that don't generally contain other values. Usually a text or date or number field that would be visible on the page is the leaf editor, and those leaf nodes are contained in a normal Editor.
In this case, it could look something like this:
public class AddressEditor extends Composite implements Editor<Address> {
// not private, fields must be visible for the driver to manipulate them
// automatically, could be package-protected, protected, or public
protected TextBox line1;//automatically maps to getLine1()/setLine1(String)
protected TextBox city;
protected TextBox zip;
public AddressEditor() {
//TODO build the fields, attach them to some parent, and
// initWidget with them
}
}
See http://www.gwtproject.org/doc/latest/DevGuideUiEditors.html#Editor_contract for more details on how this all comes together automatically with just that little wiring.

BLOB as parameter in procedure call in mybatis

This is the call in the ProductServices.xml
<update id="resetPassword" parameterType="batchReport">
{ call user_account_mng.enc_reset_password(
#{user_Id,jdbcType=VARCHAR,mode=IN},
#{encrypted_password,jdbcType=VARCHAR,mode=IN},
#{usr_id, dbcType=VARCHAR,mode=IN},
#{salt,jdbcType=VARCHAR,mode=IN},
#{ret_code,jdbcType=CHAR,mode=OUT},
#{pgp_encrypted_password,jdbcType=BLOB,mode=IN}
)}
Now BatchReport is a POJO:
(i have declared an alias for it as batchReport)
public class BatchReport
{
private String user_Id;
private String encrypted_password;
private String usr_id;
private String salt;
private String ret_code;
private byte[] pgp_encrypted_password;
public String getUser_Id() {
return user_Id;
}
public void setUser_Id(String user_Id) {
this.user_Id = user_Id;
}
public String getEncrypted_password() {
return encrypted_password;
}
public void setEncrypted_password(String encrypted_password) {
this.encrypted_password = encrypted_password;
}
public String getUsr_id() {
return usr_id;
}
public void setUsr_id(String usr_id) {
this.usr_id = usr_id;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public String getRet_code() {
return ret_code;
}
public void setRet_code(String ret_code) {
this.ret_code = ret_code;
}
public byte[] getPgp_encrypted_password() {
return pgp_encrypted_password;
}
public void setPgp_encrypted_password(byte[] pgp_encrypted_password) {
this.pgp_encrypted_password = pgp_encrypted_password;
}
}
My main class is like this :
<BatchReport batchReport = new BatchReport();
byte[] byteArray =new byte[]{1,2,3};
batchReport.setUser_Id("CHI");
batchReport.setEncrypted_password("97D6B45");
batchReport.setSalt("71L");
batchReport.setPgp_encrypted_password(byteArray);
String returnCode = productServiceObj.resetPassword(batchReport);
i am getting following error:
Error setting null parameter. Most JDBC drivers require that the JdbcType must be specified for all nullable parameters. Cause: java.sql.SQLException: Invalid column type
The error may involve com.example.services.ProductServices.resetPassword-Inline
ProductServices is a class in which the method resetPassword is declared.
Please help me with this BLOB issue.
What should be the jdbcType in the called procedure.
what value should be passed in this pgp_encrypted_password.
Okay I found the solution to the problem now the jdbcType in the query in .xml file remains the same i.e BLOB.
Next the type which gets set for passing in the values is byte[].
So everything remains same as i have covered up .
Error actually existed as the in .xml file returns an integer indicating the number of rows changed in query and I have given the function return type as String so here goes the solution for the problem it should be of type Object.