Play Framework with Ebean and PostgreSQL on localhost - postgresql

i'm new with Play-Framework, Ebeans and PostgreSQL and tried to find the right answer for days, but finally i didn't find any good solution for my problem. Maybe it is a noob-problem but for me would be important to know what i did wrong and get a right solution for my question. This would really really helps me a lot. The thing is that i always got this Error-Message when i start the localhost to get the values from the DB on "localhost/9000/users"
Execution exception
[PersistenceException: Query threw SQLException:ERROR: relation "users" does not exist Position: 61 Bind values:[] Query was: select t0.user_id as c0, t0.name as c1, t0.email as c2 from "users" t0 ]
In /.../app/controllers/Application.java at line 12.
9 public class Application extends Controller {
10
11 public static Result getAllUsers(){
12 return ok(Json.toJson(users.find.all()));
13 }
14
15 }
So,
i have a PostgreSQL-DB running on localhost.
I'm using instead of public-schemata my own schemata named "test_schema".
I also created a table named "users" with three attributes (user_ID, name, email).
I use Play Framework 2.3.0. and configured the /application.conf like this:
db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://localhost:5432/test_db"
db.default.schema=test_schema
db.default.user="postgres"
db.default.password="12345"
db.default.logStatements=true
evolutionplugin=disabled
ebean.default="models.*"
I disabled the evolution because the DB already exists and has also some entries.
So i created the Entity-Class like this:
#Entity
#Table(name="\"users\"")
public class users extends Model{
public users(int user_ID, String name, String email){
this.user_ID = user_ID;
this.name = name;
this.email = email;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int user_ID;
#Required
private String name;
#Required
private String email;
public static Finder<Integer, users> find = new Finder<Integer, users>(Integer.class, users.class);
public static List<users> all() {
return find.all();
}
public int getUserID() {
return user_ID;
}
public void setUserID(int userID) {
this.user_ID = userID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
In my Controller-Class i only have this method:
public static Result getAllUsers(){
return ok(Json.toJson(users.find.all()));
}
And the conf/routes has this entry:
GET /users controllers.Application.getAllUsers()
What could be the reason for? Are their any suggestions to make it work?

Related

POST REST request including a foreign key OnToMany Mapping

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

Create an entity that is not a table spring jpa

I'm trying to learn spring boot with JPA. How to create an entity that only has selected columns of a table? I can do this using jdbcTemplate but is it also possible using JPA?
I tried using the SELECT NEW but it gives me a null pointer exception error on the em.createQuery execution. Does it mean I get no results? Can you help me pinpoint my error?
Here is my code :
EntityManager em;
String queryStr =
"SELECT NEW com.lms.app.user.User(c.id.username, c.password, c.emailadd) FROM TBUSER AS c";
TypedQuery<User> query =
em.createQuery(queryStr, User.class);
List<User> results = query.getResultList();
User.class
public class User {
private String name;
private String password;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
TBUSER columns looks like this :
username varchar (primary key)
password
emailadd
then more columns here..

Return more data than model contains using Spring Data

I'm working with Spring Data which is great stuff, but sometimes I need to get more data from database than my model can handle. For example I have model like below.
#Entity
#Table(name = "email")
public class Mail implements Serializable {
#Getter
#Setter
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private Long id;
#Getter
#Setter
private String text;
}
An I my query will be more complex than usual. I want to get my model and in addition number of similar entities, using group by.
#Query(value = "SELECT m, COUNT(m) as countValue FROM Mail m GROUP BY m.text")
List<Mail> findAllNewsletters();
How I should handle something like that? My model does't contain countValue so I will get List<Object[]>
How to deal with that situation, keep my code clean, easiness
of using this.
Step 1: Create a container class to hold the output from your query.
class MailOccurence {
private final Mail mail;
private final Long recurrence;
public MailOccurence(final Mail mail, final Long recurrence) {
this.mail = mail;
this.recurrence = recurrence;
}
public Mail getMail() { return mail; }
public Long getRecurrence() { return recurrence; }
}
Step 2: Populate and return instances of the container class from the query.
Query(value = "SELECT new MailOccurence(m, COUNT(m)) FROM Mail m GROUP BY m.text")
List<MailGroup> findAllNewsletters();
For full details, see the JPA specification.
You can go for a DTO like following
public class MailEntry {
private Long id;
private String text;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
and inside your business logic you can take the advantage of spring template something like following
#Autowired
JdbcTemplate jdbcTemplate;
private static final String SQL = "SELECT m, COUNT(m) as countValue FROM Mail m GROUP BY m.text";
public List<MailEntry> getMailEntries() {
List<MailEntry> mailEntryList = jdbcTemplate.query(SQL, new RowMapper<MailEntry>() {
public MailEntry mapRow(ResultSet rs, int rowNum) throws SQLException {
MailEntry mailEntry = new MailEntry();
mailEntry.setId(rs.getInt(1));
mailEntry.setText(rs.getString(2));
return mailEntry;
}
});
return mailEntryList;
}
Hope this help.

JPA find from composite Key

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.

Passing multiple variables from servlet to client

I hope someone can assist me with this. I'm trying to pass an customer id and customer name from a database result using rpc in gwt to the client. I found a way to pass one variable but I can't find a way to pass them both where the id is attached to the name. Can someone post a code example on how to do this. If you need more info let me know.
That is a simple java limitation. Just wrap the 2 fields in an object.
As David Nouls said, you could just use an object, e.g.
import com.google.gwt.user.client.rpc.IsSerializable;
public class Customer implements IsSerializable {
private String id;
private String name;
public Customer(String id, String name) {
this.id = id;
this.name = name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}