I want to use table names in Postgres like "TableName". In Aqueduct the suggested class name is _tablename.
As I read the manual I can use #Table(name: "TableName") but that doesn't seem to work (or probably not understood correctly).
Is there a way to use a different table name in Postgres versus the private class name in Aqueduct?
#Table(name: "UserName")
class User extends ManagedObject<_User> implements _User {
#Serialize()
String get fullname => '$firstname $lastname';
#override
void willUpdate() {
// Add anything here to change prior to being updated.
}
#override
void willInsert() {
// Add anything here to change prior to being inserted.
}
}
class _User {
#primaryKey
int id;
#Column(nullable: false)
String firstname;
#Column(nullable: false)
String lastname;
#Column(nullable: false)
String email;
}
The #Table() annotation must be applied to the private data class which is referred to in the aqueduct documentation as the "table definition" class. In this case, the _User class:
#Table(name: "UserName")
class _User {
#primaryKey
int id;
#Column(nullable: false)
String firstname;
#Column(nullable: false)
String lastname;
#Column(nullable: false)
String email;
}
Here's a link to the api docs on the Table class.
Related
i'm new to Springboot. I'm trying to implement a simple REST api using :
-Springboot, JPA & rest along with hibernate
I have a 2 tables database, Notebook that contains 1 to many notes
I already setup the 2 tables and relationships. I also created a NotebookRepository and NoteRepository to get basic CRUD operations via the springboot rest. The Database connection and relationships are functionning
but i don't know how to add a new note (it has a notebook_id foreign key which msut NOT be NULL) and everytime i tryto post something along these lines
{
"title:"abc",
"text":"whatever",
"notebook":{
"id":2
}
}
i get this error :
Caused by: java.sql.SQLIntegrityConstraintViolationException: Column 'notebook_id' cannot be null
#Entity
#Table(name="notebook")
public class NoteBook {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="name")
private String name;
#OneToMany(mappedBy="notebook", cascade=CascadeType.ALL)
List<Note> notes;
public NoteBook() {
}
public NoteBook(String name) {
this.name = name;
}
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 List<Note> getNotes() {
return notes;
}
public void setNotes(List<Note> notes) {
this.notes = notes;
}
public void addNote(Note note) {
if(notes == null) {
notes = new ArrayList<>();
}
note.setNotebook(this);
notes.add(note);
}
#Entity
#Table(name="note")
public class Note {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="title")
private String title;
#Column(name="text")
private String text;
#ManyToOne(cascade={CascadeType.MERGE, CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinColumn(name="notebook_id")
private NoteBook notebook;
public Note() {
}
public Note(String title, String text) {
this.title = title;
this.text = text;
}
#RepositoryRestResource(collectionResourceRel = "note", path = "notes")
public interface NoteRepository extends JpaRepository<Note, Integer>{
//No code...
}
#RepositoryRestResource(collectionResourceRel = "notebook", path = "notebooks")
public interface NotebookRepository extends JpaRepository<NoteBook, Integer>{
}
The problem is that the class Note doesn't have a constructor with NoteBook parameter to pass the created NoteBook object to, so the solution is to add this constructor:
public Note(String title, String text, NoteBook noteBook) {
this.title = title;
this.text = text;
this.noteBook = noteBook;
}
and it's enough to send the JSON object as you do, but just be aware of case-sensitivity:
{ "title:"abc", "text":"whatever", "noteBook":{ "id":2 } }
I think you need to add referencedColumnName = "id" for JoinColumn annotation for notebook field in Note class.
Maybe you have problem with IDENTITY generation type. See this problem with null pointer
MY POJO looks like this:
#Document(collection = "users")
public class User {
#Id
private String id;
String username;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
I am able to save the object's values in the mongodb by calling mongoDBClient.save(userObj); as bellow:
public void save(Object paramObject) {
mongoOperations.save(paramObject);
}
The problem with this save api is that it's returning void. I want to get the same object which was saved. How can I achieve that?
paramObject is viable for introspection after save. It represents it's persistent state at that stage.
For example, the driver is responsible to assign the id on your behalf.
In addition, all properties which you don't set yourself and are designated to be populated by spring data - such as properties annotated with #CreatedDate - are also available after the save() method (assuming auditing is configured).
In any case, the Id is set. Later you can query for the same object by calling findById(paramObject.getId(), User.class)
I am using similar code to what is listed in: How to map one class with multiple tables in Hibernate/javax.persistance?
I was trying to write a sample login program, based on above example I map my user class to secondary table where I store password field. now when I retrieve back user entity. I also get secondary table field so password is also available in user object.
Is it possible, that during registration I want to use secondary table storage method but when I read back. it should not return password back with user?
How can I achieve this? I am looking for some JPA way like #transient ignore the particular column.
I wouldn't go for such implementation.
Best practice is to never store a clear-text password, but a digest instead:
#Entity
public class Account
{
#Column
private String username;
#Column(length = 32)
private String password;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = DigestUtils.md5Hex(password);
}
}
It's an uncommon requirement, and JPA patterns will do their best to fight against you :)
But... some way may still be possible:
using Entity Listeners:
#Entity
public class Account
{
#Column
private String username;
#Column
private String password;
#PostLoad
public void postLoad()
{
password = null;
}
}
be careful: when loaded inside a transaction, a null password may be eventually flushed on commit.
removing getter for password:
if you put annotations only on fields, you can remove getPassword() method. Even if the field is populated on load, it's not accessible by external java code.
using a #Transient combination:
#Entity
public class Account
{
#Column
private String username;
#Column
private String password;
#Transient
private String password2;
public String getPassword()
{
return password2;
}
public void setPassword(String password)
{
this.password = password;
this.password2 = password;
}
}
Am trying to create a model class to store an Entity in Google App Engine using Eclipse.But when i save my work i get the error message:
org.datanucleus.metadata.MetaDataManager initialiseFileMetaDataForUse.
SEVERE: Class "com.packagename.classname" has been specified with an object-id class javax.jdo.identity.StringIdentity yet no fields have been identified as primary key fields. Please notate using the "primary-key" tag against the fields that should be considered part of the primary key.
If my understanding of JPA is correct, i do not need a primary-key for an entity since i already have a #Id tag.Here is my class.
#Entity
public class MyCLassName {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private static String userName;
private static String location;
private static Date dateOfBirth;
private static int age;
private static String gender;
private static String teamName;
private static int weight;
//Constructor with arguments
public MyClassName(String userName, String location, String gender, int age, Date DOB, int weight) {
MyClassName.userName = userName;
MyClassName.location = location;
MyClassName.gender = gender;
MyClassName.age=age;
MyClassName = DOB;
MyClassName.weight = weight;
}
//setter methods
public static void setUserName(String userName) {
MyClassName.userName = userName;
}
public static void setLocation(String location) {
MyClassName.location = location;
}
public static void setGender(String gender) {
MyClassName.gender = gender;
}
public static void setAge(int age) {
MyClassName.age = age;
}
public static void setDateOfBirth(Date dateOfBirth) {
MyClassName.dateOfBirth = dateOfBirth;
}
public static void setWeight(int weight) {
MyClassName.weight = weight;
}
//getter methods
public static String getUserName() {
return userName;
}
public static int getWeight() {
return weight;
}
public static String getLocation() {
return location;
}
public static String getGender() {
return gender;
}
public static String getTeamName() {
return teamName;
}
public static Date getDateOfBirth() {
return dateOfBirth;
}
public static int getAge() {
return age;
}
}
What exactly am i doing wrong here?
Your understanding of JPA is partially correct. You do not need to assign the primary key because you have used the #Id and #GeneratedValue annotation. The JPA implementation will automatically generate the primary key value as a long integer. However it still needs a field in which to store this ID value. It is trying to do that in userName. See Java Tutorial ID Generation Type: IDENTITY for example.
I have a class like this...
#Entity
public class User{
private String userId;
#Id
public String getUserId(){
return userId;
}
public void setUserId(String userId){
this.userId = userId;
}
}
#Embeddible
public class RegPk{
private String serial;
private String userId;
....
}
#Entity
#IdClass(RegPk.class)
public class Registration {
private String userId, serial;
private User user
#Id
#Column(name="SRL_C")
public String getSerial() {return serial;}
public void setSerial(String serial) {this.serial = serial;}
#ManyToOne(cascade={CascadeType.REFRESH})
#JoinColumn(name="USERID", referencedColumnName="USERID", nullable = false)
public User getUser() {return user;}
public void setUser(User user) {this.user = user;}
#Id
#Column(name="USERID", nullable = false)
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
RegPk pk = new RegPk();
pk.setSerial(dr.getSerial());
pk.setUserId(dr.getUserId());
Registration userOld = em.find(Registration.class, pk);
But when I try to run it I get null back. I swear I thought I had it working so...
1.) is this kind of thing even possible?
2.) what am I doing wrong?
Yes, it's possible, provided you use the MapsId annotation. Otherwise, you have two different fields mapped to the same column, which is invalid.
The javadoc provides an example which almost matches exactly with your situation.