Auto Increment like with String values in hibernate - java

Well i want to know if there is a much appropriate way to tackle generating auto id with string values, my first idea is creating an auto increment id which we can call auto_id then before saving a new entity I'll query for the latest data inside the db to get the id then I'll add 1 to my auto generate value column that I assign name which is stringValue+(id+1) though I'm concerned on how it will affect the performance as to saving this entity needs two access in db which is fetching and saving... like my question earlier is there a much appropriate way to handle this scenario?
And also sorry for my English guys if you want to clarify things with my question kindly ask, thnx in advance..
Here's my code for AttributeModel for hibernate annotation
#Component
#Entity
#Table(name="attribute_info")
public class AttributeModel {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="attr_id", nullable=false, unique=true)
private int id;
#Column(name="attr_name")
private String name;
#Column(name="attr_desc")
private String desc;
#Column(name="attr_active")
private int active;
#Column(name="attr_abbr")
private String abbr;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name="stats_id", referencedColumnName="stats_id")
private BaseStatisticModel baseStats;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
public String getAbbr() {
return abbr;
}
public void setAbbr(String abbr) {
this.abbr = abbr;
}
public BaseStatisticModel getBaseStats() {
return baseStats;
}
public void setBaseStats(BaseStatisticModel baseStats) {
this.baseStats = baseStats;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}

I can only say "Don't do it". How is a String ID like "str10001" better than 10001? It can't be an optimization as strings take more memory and more time. So I guess you need to pass it to some String-expecting method later.
If so, then pass "str" + id instead. Constructing the string on the fly surely won't saturate your server.
If not, then let us know what you actually need rather than what you think it could help you to achieve it.
I'm pretty sure, Hibernate can't do it. It couldn't some long time ago I checked it recently and it makes no sense (in any case, it's not a feature crowds would request).

Related

Create controller for "generic" path mapping springboot

Let's assume I have many teams like : "Team A, Team B...Team Z" and each team has at least 5 components. Now I want to create a generic controller that responds to any request of type /team/number so I can be able to get informations about a team member.
For example my controller must be able to map this request :
#RequestMapping(value = "/Team A/1", method = RequestMethod.GET)
Team class could be :
#Entity
#Table(name = "team")
public class Team {
public Team() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private List<Player> players;
}
And
Player :
#Entity
#Table(name = "player")
public class Player {
public Player() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private int number;
}
Obviously it can either execute GET and POST. The point is that I don't want to specify a controller for each team and each number, I just want one that can respond to /String/int .
I need also to specify which string it can accept and the range of values (max 5 for example).
The #PathVariable spring annotation would help you in this case.
For example:
#RequestMapping(value = "{team}/{component}", method = RequestMethod.GET)
public Team getTeam(#PathVariable String team, #PathVariable int component) {
//Use team and component here
}
You can just add some logic into the controller method to throw some exception if either variable is an unexpected value.
Though depending on what you are trying to achieve, this may be a bad design as this controller method will catch all GET requests that match String/int. You may want to try something like this to make the request mapping more specific:
#RequestMapping(value = "team/{teamLetter}/{component}", method = RequestMethod.GET)
public Team getTeam(#PathVariable char teamLetter, #PathVariable int component) {
//Use team and component here
}

AWS DynamoDB - save a JSON Array to a table (Java/Android)

How do you save a JSON Array as an item attribute? AWS documentation is the absolute worst thing ever - it contradicts itself, a lot of things are either redundant or only partially explained, some things aren't explained at all - I don't know how anyone manages to use it.
Anyway, suppose I have a table called Paths, and a path has a name, an ID, and a list of LatLngs (formatted as a JSON Array)
In the class definition for this table, I have
#DynamoDBTable(tableName = "Paths")
public class Path {
private String id;
private String name;
private JSONArray outlineJSON;
with getters and setters like
#DynamoDBRangeKey(attributeName = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
which works fine for strings, booleans and numbers, and the object saves successfully to the table.
AWS documentation mentions JSON several times, and says it can handle lists, but it doesn't explain how to use lists or give any examples.
I used #DynamoDBHashKey for the id, #DynamoDBRangeKey for name, and #DynamoDBAttribute for other strings, numbers or booleans, and I tried it here
#DynamoDBAttribute(attributeName = "outline")
private JSONArray getOutlineJSON() {
return outlineJSON;
}
private void setOutlineJSON(JSONArray outlineJSON) {
this.outlineJSON = outlineJSON;
}
It successfully saved the object but without the array.
How do I save the array? I can't find an explanation anywhere. I think #DynamoDBDocument might have something to do with it, but all the documentation on the subject gives unrelated examples, and I can't find any using a list like my in situation.
EDIT: For now, I have a working solution - I can easily convert my lists to JSONArrays and then convert those to Strings, and vice-versa.
You can define your class to be something like
#DynamoDBTable(tableName = "Paths")
public class Path {
private String id;
private String name;
private LatLang latLangs;
#DynamoDBHashKey(attributeName="id")
public String getId() { return id;}
public void setId(String id) {this.id = id;}
#DynamoDBRangeKey(attributeName = "name")
public String getName() { return name; }
public void setName(String name) { this.name = name; }
#DynamoDBDocument
public static class LatLang{
public String lat;
public String lang;
}
}

Android and DynamoDB. Not being able to add an attribute to table

I created a table in AWS DynamoDB which I'll be using for a basic questions and answers forum I'm developing and after table creation and some successful tests where I was able to insert data I decided to add an attribute for storing date of question, which I called time_stamp but for an unknown reason for me I'm not being able to refresh table structure, I mean, data is still saved with no errors but with no time_stamp field.
I tried deleting the table and recreating several times and modifying time_stamp data type with no success so I'm lost and I hope anyone can help me. I thought the only neccesary thing to alter table structure in DynamoDB is just modifing the mapping class in Java but cannot make it to work.
My mapping class is the next:
import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.*;
#DynamoDBTable(tableName = "community_questions")
public class CommunityQuestion {
private long question_id;
private String time_stamp;
private String user_id;
private String subject;
private String question;
#DynamoDBHashKey(attributeName = "question_id")
public long getQuestionId() { return question_id; }
public void setQuestionId(long questionId) { this.question_id = questionId; }
#DynamoDBAttribute (attributeName = "time_stamp")
public String geTimeStamp() {
return time_stamp;
}
public void setTimeStamp(String timeStamp) {
this.time_stamp = timeStamp;
}
#DynamoDBAttribute (attributeName = "user_id")
public String getUserId() {
return user_id;
}
public void setUserId(String userId) {
this.user_id = userId;
}
#DynamoDBAttribute(attributeName = "subject")
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
#DynamoDBAttribute(attributeName = "question")
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
}
All data is being saved with no errors but time_stamp won't!!
I'm using mapper.save for saving operations.
Maybe anything I should refresh in AWS console?? Can't find anything.
Please help, and many thanks in advance.
There is a typo in your code. Rename geTimeStamp to getTimeStamp
DynamoDbMapper considers only methods with exactly "get" or "is" prefixes, and then checks for annotations on those in a second step. Its not picking up your added property because of that.
/**
* Returns whether the method given is a getter method we should serialize /
* deserialize to the service. The method must begin with "get" or "is",
* have no arguments, belong to a class that declares its table, and not be
* marked ignored.
*/
private static boolean isRelevantGetter(Method m) {
(soure)

Lambda in Java - Could not analyze lambda code

I’ve got an application with Hibernate (JPA) which I am using in combination with Jinq. I’ve got a table which lists entities and I want the user to be able to filter it. In the table there are persons listed.
#Entity
public class Person {
private String firstName;
private String surName;
#Id
private int id;
public Person() {
}
public Person(final String pFirstName, final String pSurName, final int pID) {
firstName = pFirstName;
surName = pSurName;
id = pID;
}
public int getId() {
return id;
}
public void setId(final int pID) {
id = pID;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String pFirstName) {
return firstName = pFirstName;
}
public String getSurName() {
return surName;
}
public void setSurName(final String pSurName) {
surName = pSurName;
}
}
I am using JavaFX for this, but this shouldn’t matter. First thing I tried was to filter the persons by their surname. For filtering, I used Jinq in combination with lambda. My filtering code looks like this:
private List<Person> getFilteredPersons(final String pSurName){
JPAJinqStream<Person> stream = streamProvider.streamAll(Person.class);
stream.where(person -> person.getSurName().contains(pSurName));
List<Person> filteredList = stream.toList();
stream.close();
return filteredList;
}
So the object I am operating on is a normal String. I don’t think that my Person class has anything to do with that. My first thought was, that you can’t use the method boolean contains(...) in lambda because when the error showed up, it said:
Caused by: java.lang.IllegalArgumentException: Could not analyze lambda code
So my question is, is it somehow possible to use the contains-method of a String in lambdacode?
Your question has nothing to do with JPA or lambdas, but everything to do with jinq: it simply doesn't support translating String.contains() to a database query. See http://www.jinq.org/docs/queries.html#N65890 for what is supported.

Save entity after unique constraint exception

i have an entity with a unique name.
In my example i save two persons with the same name. At the second time comes an "EntityExists" (Unique) Exception, that was the expected behavior.
After it i changed name and set the "ID" to null.
Than i try to persist it again but i get "org.apache.openjpa.persistence.EntityExistsException: Attempt to persist detached object "com.Person#1117a20". If this is a new instance, make sure any version and/or auto-generated primary key fields are null/default when persisting.
without the version it works but i find no solution to "reset" the version number.
Can someone help me?
Update: My new problem is, that i have a base entity an two pcVersionInit (look at my answer at bottom) i can't override it, i tried it in base and normal entity what is the best practise now instead of "override" the value in pcVersionInit ? Copy Constructor?"
public class Starter{
private static EntityManager em;
public static void main(String[] args) {
em = Persistence.createEntityManagerFactory("openjpa")
.createEntityManager();
Person p1 = new Person("TEST");
savePerson(p1);
Person p2 = null;
try{
p2 = new Person("TEST");
savePerson(p2);
}catch(Exception e){
p2.setId(null);
p2.setName(p2.getName()+"2");
em.persist(p2);
}
}
private static void savePerson(Person person){
em.getTransaction().begin();
em.persist(person);
em.getTransaction().commit();
}
}
Person.class:
#Entity
public class Person implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE,generator="seqGenerator")
#SequenceGenerator(name="seqGenerator",sequenceName="personSeq")
private Long id;
#Version
private Long version;
#Column(nullable=true, unique=true)
private String name;
public Person(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
}
First off, stay away from messing around with pcVersionInit. I'd suggest to create a copy constructor in your Person Entity and in the event of rollback create a new one using the copy constructor.
Okay the problem is that OpenJPA adds a field named pcVersionInit (with #version) and set it "true" after try to persist. If i use reflection to set it to false, it works. Other way is a copy constructor.

Categories