Automatically Insert first row soon after table is created / recreated using Hibernate - java

I want Username = Administrator and Password = admin, soon after table is created (or whenever table is recreate).
Is there any way to insert first row using following code. I do not want to use a separate insert query
Is there any constraint in Hibernate to restrict user from deleting (first) row
#Entity
#Table(name = "Users")
public class Users implements Serializable {
#Id
#Column(name = "Username", unique = true, nullable = false)
private String username;
#Column(name = "Password", nullable = false)
private String password;
/**************** getter & setter ************/
}

What you seem to be looking for is called fixtures. With Hibernate you can supply import.sql file on your classpath with your initial data (insert statements).
There's a bit more information on the JBoss' site.
The import.sql file is a simple text file with SQL statements, one line per statement:
insert into users (id, username) values (1, 'administrator');
insert into users (id, username) values (2, 'user');
...

Related

only select columns of the a psql table could receive data

Something very bizarre have been happening. I have a very simple Entity recipe like so
#Data
#Entity
#Table(name = "recipe", schema = "public")
#AllArgsConstructor
#NoArgsConstructor
public class Recipe {
#Id
#GeneratedValue(
strategy = GenerationType.IDENTITY
)
#Column(name = "id", updatable = false, nullable = false)
private long id;
#Column(name = "name")
private String name;
#Column(name = "instructions")
private String instructions;
#Column(name = "date_added", nullable = false)
private String dateAdded;
#Column(name = "last_edited", nullable = false)
private String lastEdited;
}
and I have this post service that should post the 4 string attribute to the database
public void postRecipe(Recipe recipe){
var sql = """
INSERT INTO public.recipe ("name","instructions","date_added","last_edited")
VALUES (?, ?, ?, ?)
""";
jdbcTemplate.update(
sql,
recipe.getName(),
recipe.getInstructions(),
recipe.getDateAdded(),
recipe.getLastEdited()
);
}
However when the following jason is sent using postman, I get the null value error.
{
"name":"test",
"instructions":"don't eat",
"date_added":"03/04/2017",
"last_edited":"03/04/2017"
}
ERROR: null value in column \"date_added\" of relation \"recipe\" violates not-null constraint\n Detail: Failing row contains (3, null, don't eat, null, test)
The strangest thing is that only the "name" and "instruction" columns receive their data and not the other columns. I have tried adding another String attribute to the Entity class and it also cannot get data from the jason.
Edit 1:
I have tried adding the data directly through pgadmin and it worked fine
INSERT INTO recipe (name, instructions, date_added, last_edited)
VALUES ('test', 'test instruction', '2020/03/05', '2020/05/08');
It looks like your deserialization is broken - transforming your JSON into the Java entity, which results in some null values present. Most likely because date_added != dateAdded (field name), and Jackson cannot properly set a value.
I recommend having a look at Jackson guide: https://www.baeldung.com/jackson-annotations, #JsonProperty specifically. And overall do not mix entities and DTOs
After many trials and errors I was able to come up with a solution but still have no clue as to why this is happening. It turns out the under score in the annotation is the problem.
//won't work
#Column(name = date_added)
//works
#Column(name = dateadded)
This is pretty strange because I am fairly certain that the under score is generated by hibernate.
if anyone know why this is happening please let me know... for now I will just stay away from the under scrolls.

DataException: could not execute query

I get this error when I try to run start my application:
org.springframework.dao.DataIntegrityViolationException: could not execute query; SQL [SELECT * FROM testquestions ORDER by id DESC LIMIT 1]; nested exception is org.hibernate.exception.DataException: could not execute query
As seen in previous problems on StackOverflow, I tried to adjust the length of my data input in my sql file and I've set the length of my #Column to the same amount of characters. this didn't help.
this is my #Table class:
#Entity
#Getter
#Setter
#Table(name = "testquestions")
public class TestQuestion {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "questiontitle", length = 2000)
private String questionTitle;
#Column(name = "info", length = 4096)
private String Info;
#Column(name = "solvetime")
private int solveTime;
#Column(name = "difficultylevel")
private DifficultyLevel difficultyLevel;
#Column(name = "questionimage")
private Image questionImage;
public TestQuestion(){
}
public TestQuestion(int id, String questionTitle, String info, DifficultyLevel difficultyLevel) {
this.id = id;
this.questionTitle = questionTitle;
Info = info;
this.difficultyLevel = difficultyLevel;
}
public String getInfo() {
return Info;
}
}
This is my # Query in my QuestionRepository:
#Query(value = "SELECT * FROM testquestions ORDER by id DESC LIMIT 1", nativeQuery = true)
TestQuestion fetchLastQuestion();
This is my database.sql file, it writes to a PostgreSQL data base:
TRUNCATE TABLE users CASCADE;
TRUNCATE TABLE testquestions CASCADE;
DROP TABLE users;
DROP TABLE testquestions;
CREATE TABLE users(
id int,
username varchar(255),
password varchar(255),
role varchar(255)
);
CREATE TABLE testquestions(
id int primary key ,
questiontitle varchar(2000),
info varchar(4096),
solvetime int,
difficultylevel varchar(255),
questionimage bytea
);
INSERT INTO users(id, username, password, role)
VALUES (0, 'user', 'u', 'user'),
(1, 'user','u','user');
INSERT INTO testquestions(id,questiontitle, info, solvetime, difficultylevel, questionimage)
VALUES (0, 'Multiple Databases', 'A company wants to use Spring Boot in a web application which should use JPA as a database abstraction. The unit tests should be run on an H2 database while the production should run on a MySQL database.
Select all the things that need to be done or that will be done automatically by Spring Boot.', 3, 'Easy',
''),
(1, 'Screen Orientation', 'Which of these methods are called when the screen changes orientation from portrait to landscape in Android?',
3, 'Easy',''),
(2, 'Merge Names', 'Implement the uniqueNames method. When passed two arrays of names, it will return an array containing the names that appear in either or both arrays. The returned array should have no duplicates.
For example, calling MergeNames.uniqueNames(new String[]{''Ava'', ''Emma'', ''Olivia''}, new String[]{''Olivia'', ''Sophia'', ''Emma''}) should return an array containing Ava, Emma, Olivia, and Sophia in any order.',
10, 'Easy',''),
(3, 'Date', 'Write a function that converts user entered date formatted as M/D/YYYY to a format required by an API (YYYYMMDD). The parameter "userDate" and the return value are strings.
For example, it should convert user entered date "12/31/2014" to "20141231" suitable for the API.', 10, 'Easy', ''),
(4, 'Inspector', 'Fix the bugs in the following HTML code.', 10, 'Easy',''),
(5, 'Train Composition', 'A TrainComposition is built by attaching and detaching wagons from the left and the right sides, efficiently with respect to time used.
For example, if we start by attaching wagon 7 from the left followed by attaching wagon 13, again from the left, we get a composition of two wagons (13 and 7 from left to right). Now the first wagon that can be detached from the right is 7 and the first that can be detached from the left is 13.
Implement a TrainComposition that models this problem.', 20, 'Hard', '');
Has anyone got an idea how to fix this error?
Thanks!
Tom

Hibernate doesn't persist when inserting long texts

I'm using Postgresql 9.6 and before I was using mySQL an I get the same problem with the two databases. I also have the same problem with Hibernate 4 and 5.
When I'm trying to persist an Object with a long String inside, it never ends the method session.persist(object). In the other hand it works perfectly when the string ismySQL an I get the same problem with the two databases.
not that long, like this paragraph.
addVehicle method in VehicleDAO.java
public Vehicle addVehicle(Vehicle vehicle) {
Session session =
this.sessionFactory.getCurrentSession();
session.persist(vehicle);
return vehicle;
}
Vehicle attributes:
public class Vehicle {
#Id
#Column(name = "idvehicle")
#GeneratedValue(strategy = GenerationType.IDENTITY)
int idVehicle;
#Column(name = "name")
String name;
#Column(name = "description")
String description;
#Column(name = "photob64")
String photoB64;
Eclipse console log:
Hibernate: insert into vehicle (description, name, photob64, idvehicletype) values (?, ?, ?, ?)
Hibernate doesn't persist when inserting long texts
As per your question, it doesn't persist when inserting long texts. It's is because by default String lenght is 255. You can see in database. The VARCHAR(255) lenght is 255.
You can mentioned length by using below approach:
#Column(name=" description", length = 300)
private String description;
If you are not sure of length, then it's good idea to go with lob, blob or clob as per your need. You can read details of lob, blob and clob and select one of them. For text lob or clob will work for you.
There are two ways,
You can set columnDefinition like
#Column(name = "notes", columnDefinition = "varchar(300)")
private String notes;
If you don't know maximum length of string you can set columnDefinition as text like
#Column(name = "notes", columnDefinition = "text")
private String notes;
I figured out what was happening. The method persist never ended because the information couldn't be transferred completely to the DB which was in other device, a Raspberry Pi.
I changed the MTU of the network adapters of my PC and Raspberry Pi to 1492 with the command:
sudo ifconfig eth0 mtu 1492
More info: http://www.ubuntugeek.com/how-to-change-mtu-maximum-transmission-unit-of-network-interface-in-ubuntu-linux.html

What hibernate do with unmapped column?

Suppose there is a class like that:
public class Entity {
private Long id;
private String name;
}
And table with 3 columns: id, name and address.
CREATE TABLE entity (
id NUMBER(9,0),
name VARCHAR2(255),
address VARCHAR2(1000),
Then en insert was performed:
INSERT INTO entity (id, name, address) VALUES (1, "a", "b")
Then we load and update hibernate entity:
Session session = ...
Entity entity = session.get(Entity.class, 1);
Then update name and save it again:
entity.setName("newName");
session.save(entity);
So what is address column value now - null or b? Does hibernate provide some stgrategies for such situations or I have to
add address field into entity and mark it as #Column(updatable=false, insertable = false)?
If you would put the following properties in persistence.xml(or where you have defined your hibernate properties)
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="false"/>
Then you could see the queries executed by hibernate when server is run in debug mode with logged configured for debug.
If your entity is
public class Entity {
private Long id;
private String name;
private String secondName;
//Getters & Setters
}
Then executing below HQL
SELECT e FROM Entity e WHERE e.id = 121
would produce results similar to
SELECT entity0_.id AS id1_63_,
entity0_.name AS name6_63_,
entity0_.secondName AS secondName6_63_,
FROM yout_db.Entity entity0_
WHERE entity0_.id = 121
You see that here SELECT * FROM Entity was not executed instead all the fields from the Class were fetched and added to the query. So if you have ignored any field from DB then it will NOT be taking part in Queries.
For Select-Update also same thing happens.
entity.setName("newName");
session.save(entity);
Below is formatted query if you would update an entity:
UPDATE your_db.Entity
SET name = ?
secondName = ?
WHERE id = ?
This query will be executed even if only one field is changed.
Hibernate operates only with columns taken from entities, based on property name or described in annotation. So in your case 'address' value will be 'b'.

Hibernate - byNaturalId not working

I have a user entity identified by two natural ids, something like
#Entity
#Table(name = "user", uniqueConstraints =
{ #UniqueConstraint(columnNames = "email"),
#UniqueConstraint(columnNames = "nick") })
public User()
{}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private id;
#Column(name = "email", unique = true, nullable = false, length = 31)
#NaturalId(mutable = true)
private String email;
#Column(name = "nick", unique = true, nullable = false, length = 31)
#NaturalId(mutable = false)
private String nick;
However, when I try to execute
session.byNaturalId(User.class).with(LockOptions.READ).using("email", "admin#mail.com").load();
it throws an exception
org.hibernate.HibernateException: Entity [pervasive.com.gmail.tigerjack89.forum.shared.model.entities.User] defines its natural-id with 2 properties but only 1 were specified
at org.hibernate.event.spi.ResolveNaturalIdEvent.<init>(ResolveNaturalIdEvent.java:75)
at org.hibernate.event.spi.ResolveNaturalIdEvent.<init>(ResolveNaturalIdEvent.java:52)
at org.hibernate.internal.SessionImpl$BaseNaturalIdLoadAccessImpl.resolveNaturalId(SessionImpl.java:2607)
at org.hibernate.internal.SessionImpl$NaturalIdLoadAccessImpl.load(SessionImpl.java:2722)
at pervasive.com.gmail.tigerjack89.forum.server.model.orm.StorageManager.getByNaturalId(StorageManager.java:217)
at pervasive.com.gmail.tigerjack89.test.local.MyHibernateTest.test1(MyHibernateTest.java:37)
at pervasive.com.gmail.tigerjack89.test.local.MyHibernateTest.main(MyHibernateTest.java:23)
Why is this? I think it's also due to the log of the SQL syntax generated by Hibernate. Indeed, it is strange (redundant) at this point and I think it's the cause of the exception
Hibernate:
alter table user
add constraint UK_t8tbwelrnviudxdaggwr1kd9b unique (email, nick)
Hibernate:
alter table user
add constraint UK_ob8kqyqqgmefl0aco34akdtpe unique (email)
Hibernate:
alter table user
add constraint UK_pvnbxcfihb58o5n2n1fnc7fh1 unique (nick)
EDIT: Reading the code again, I thought that the problem could be related to the #UniqueConstraints annotations. However, even if I try to remove one of them, Hibernate continues to genetate the above SQL syntax.
I would make the email address alone the NaturalId and then your query would work.
When two columns are identified as the NaturalId it creates a Composite Key.
Nick could still be used as a foreign Key.
You've a composite naturalId key (email,nick) so you can have multiples results with simple email arg.
you've to use
session
.byNaturalId(User.class)
.with(LockOptions.READ)
.using("email", "admin#mail.com")
.using("nick", "admin")
.load();
You can also use Metamodel
session
.byNaturalId(User.class)
.with(LockOptions.READ)
.using(User_.email.getName(), "admin#mail.com")
.using(User_.nick.getName(), "admin")
.load();

Categories

Resources