Spring boot SQL script manually - java

I got a task, to create a basic app with some database handling.
I'm really new at this, the whole spring boot and stuff.
I did all the GET, PUT, POST, DELETE stuff without writing any line of SQL, starts with table creation.
But they asked me to provide the SQL script, how I managed to create the database structure, connections and stuff.
How can I solve this problem?

Add following to spring.jpa.properties
spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-source=metadata
Please refer this article https://www.baeldung.com/spring-data-jpa-generate-db-schema by #baeldung for more detail.

The most simple way to do this is to create in the resources folder a file named schema.sql with all your queries concerning the DDL (tables creation...) and a data.sql if needed where you can add INSERT queries to populate your database.
In the application.properties then you have to add spring.jpa.hibernate.ddl-auto=none to disable the schema creation of JPA and let Spring Boot executes those scripts at startup automatically.
If you want something more powerful, you should try Liquibase or Flyway.

You can used Jpa Like JpaRepository interface. You don't need write any SQL query we use it just used config your data base into Application.Property like database type
Your user name and password
public interface UserRepository extends CrudRepository<User, Integer> {}
when execute this code you can used create user , get find all user , find user by id , delete user and update user
and used #Entity annotaion into Entity class
the Entity class Represent Table into your database
#Entity
#Table(name="user")
public class User{
#Colume(name="id")
private Long id;
#Colume(name="name")
private String name;
//getter and setter here
}
when run this class your data base contract User table with id and
name
this link create spring boot application with database
https://spring.io/guides/gs/accessing-data-mysql/

Related

How to create a view or table from an Entity?

I have a question regarding views in the context of jpa entities in SpringBoot. Up to now I am using the auto create feature that automatically creates the tables by the definitions of the entities in Java. Now my application has grown so far that I need to use views. I do not want to write and maintain the sql create statements for all tables/entities otherwise I could simple add the create view statement to the schema.sql file, which I do not want to use. Instead I have a commandLineRunner that creates the views after startup but when testing the app it fails because the entities reference the views before the idividual views are created.
So is there a way to write an sql create statement in the entity maybe with an annotation to create a view during entity instantiation?
On startup you can initialize a data bootstrap. I got the code from here, which basically is a void method with your repository Autowired where you are able to create and load your data on startup of Spring.
I have implemented this dataloader in my own code and you can find this on my public GitHub.
By using an abstract class you can extend the methods (to seperate dev from prod class loaders) and with IoC you set the repository and load the data. I use CRUD with Redis, but it's pretty universal.
private final PriceRepository priceRepository;
#Autowired
public ProductionDataLoader(PriceRepository priceRepository, KeywordRepository keywordRepository, AccountRepository accountRepository) {
this.priceRepository = priceRepository;
}
#Override
public void loadEnvironmentSpecificData() {
doSomethingWithData();
}
By using #Profile annotations you can seperate dev from prod for example.
This is a hobby project of mine, I'm in no way a (certified) developer...
I found a very simple way, how to create a view without having to create all tables that have been managed by JPA with the entity instantiation automatically.
Basically I let spring boot start up and create all tables. This includes creating a table with the same name as the desired view by the JPA entity.
After startup I simply drop the table and then create my own view in an sql script.
It works very well and the entity keeps using the view after the table is dropped because they both have the same name.
Here is some code:
public class StartUpRunner implements CommandLineRunner {
public static final String VIEW_INIT_FILE = "after_hibernate_init.sql";
#Autowired
private DataSource dataSource;
#Override
public void run(String... arg) throws Exception {
createSQLViews();
}
private void createSQLViews(){
boolean IGNORE_FAILED_DROPS = true;
ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator(false, IGNORE_FAILED_DROPS , "UTF-8", new ClassPathResource(VIEW_INIT_FILE));
resourceDatabasePopulator.execute(dataSource);
}
}
And in the sql file there should be something like:
DROP TABLE IF exists YOUR_VIEW_NAME;
CREATE OR REPLACE View YOUR_VIEW_NAME
//Your view creation statement here....
It is very important to set the flag "ignore failed drops" to true because after the first startup the view will already exist and the sql script fails on the drop tables statement which would shut down the application. This way SpringBoot ignores the failed statement and starts up normally.
A downside to this approch is that you cannot test the view with #DataJpaTest anymore since the StartUpRunner needs to create the view. At least if you are like me and use the embedded H2 database from SpringBoot, which needs to be initialized before every test class.
My test annotation for testing the views looks like this:
#ActiveProfiles("sqltest")
#ExtendWith(SpringExtension.class)
#SpringBootTest
#TestMethodOrder(MethodOrderer.OrderAnnotation.class)
I am using the testMethodOrder because the sql inserted data is not cleared after each test anymore and I only insert the data before the first test and use it in all tests.
The activeProfiles annotation should be relatively self-explanatory. There I specify the test H2 database and other app specific settings.
Feel free to ask more about this approach on how to squash views into the auto-create feature of JPA.

GCP Datastore Querying on nested entity references (entityB.name)

I am having trouble figuring out if GCP Datastore supports querying nested properties of an entity.
My use case right now is like so:
Module
-> Application
Module
Application
#Entity
class Module {
Long id;
#Reference
Applicaiton application;
}
#Entity
class Application {
Long id;
String name;
}
I want to try query the module based on its nested Application name. I have tried providing the filter like so without success:
Query<? extends BaseEntity> query = Query.newEntityQueryBuilder()
.setKind("module")
.setFilter(PropertyFilter.eq("application.name", "UserApp"))
.build();
I'm using Springs GCP datastore abstraction through their DatastoreTemplate, but this doesn't seem related given that when I try run the GQL on the GCP console I get no results back either.
SELECT * FROM module WHERE application.name = "UserApp"
Thanks for taking the time to read through this. Any help with this is greatly appreciated!
It looks like you are using a Reference and not an embedded entity. The Application in module is really a key reference to an Application entity. Thus the values of application are not an indexed on the Module entity.

How to make a connection between an external mysql database and then call in for specific data queries

I am working on a springboot project and I am a total newbie in this. We are told to complete the project within a given time period and the deadline is in 3 days. I have a string which will contain the username. I am said that there will be an external database from where we have to fetch the data of that user and return that to the application. We are working on a web api.
Till now I have somehow extracted the username from the encoded data but now I am unable to proceed further. All the resources available online are related to building a repository and their own data and use that in the program but I have to use it from an external database. I don't know anything about this and is completely stuck.
The external database is a sample and includes an id , username and data. From the username we have to search the database and return all the three details as a JSON format of that user.
Well that was simple in SQL but I don't know how that can be performed from the point where I am now.
Thank You.
There is a special file called application.properties in Spring Boot, where you can define your authorization data to get connection with your remote database.
Usually, you should specify basic data:
spring.datasource.url=jdbc:mysql://url-to-your-external-db/name-of-db
spring.datasource.username=your_username
spring.datasource.password=your_pasword
After that, you could retrieve your data from database using JpaRepository for example. There is plenty of frameworks that will serialize/deserialize your Java objects/entities to JSON (Jackson for example).
Example of fetching users from a database using JpaRepository:
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByFirstName(String firstName)
}
where User could be your POJO which represents a table with users in database.

Using #Entity Class When Table Doesn't Exist

I have several database tables that my Spring MVC/JPA application refers to using the #Entity and #Table Annotations. I've run into the issue where if my application switches between database connections, some tables that exist on database 1 may not exist in database 2 (as we are following the SDLC cycle and promoting table additions/changes after they get the "OK"), thus resulting in an SQL Exception when the application server starts.
Does spring offer a way to mark specific #Entity Classes as "Optional" or "Transactional" so there are no database Exceptions returned because of nonexistant tables?
In my opinion, there is no option to do that.
You can add automatic update of schema in Hibernate, but you mentioned that you are doing this manually.
Hibernate is validating the schema, when he establishes connection. You use #Entity, so he looks for that table and throws an error if there is no with the name specified.

Dto class not creating mysql db table if Transient object values used

#Entity
#Table(name="timesheet")
public class TimeSheet extends HibernateDaoSupport implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="timesheetid")
private int timesheetid;
#Transient
private Employee employeeName;
-
-
-
}
In the above code I use annotations with hibernate to create tables in mysql backend.
Table is not getting created while running this code .
There is no exception in the console.
I have used the similar code prior to create many tables.Now its not working .
Is there anything i am missing ?
Kindly help.
The point of Hibernate is not to create database tables, but to use them. You may ask Hibernate to create the schema for you in development, but that should be used only for quick prototyping, and certaily not on a production database.
See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#configuration-misc-properties. You must use the hibernate.hbm2ddl.auto property to tell Hibernate to create or update database tables when the session factory is created.

Categories

Resources