The DB does not populate with the data - java

I ve created a table in Postgres and do a relation in java code :
#Getter
#Setter
#Entity
#Table(name = "resources")
public class Resource {
#Id
#Column(name = "raport_id")
private BigDecimal raportId;
#Column(name = "reference_id")
private String referenceId;
}
Also I created a repository
public class ResourcesRepository {
#PersistenceContext
private EntityManager entityManager;
public void persist(BigDecimal raportId, String referenceId, String type) {
Resource resource = new Resource();
resource.setRaportSysId(raportId);
resource.setReferenceId(referenceId);
entityManager.persist(raport);
}
public void updateRaportId(BigDecimal raportId) {
entityManager.createQuery("UPDATE Resource r set r.raportId = :raportId ")
.setParameter("raportId", raportId)
.executeUpdate();
}
}
I am passing the parameter raportId in dofferent location invoking the query like this:
ResourcesRepository.updateRaportId(raport.getId());
I do not have any errors but the table is not populated. Wonder what I am doing wrong? Should I use Insert INTO instead of update?

make sure you commit your transaction after update/persist

Related

org.hibernate.hql.internal.ast.QuerySyntaxException: Apartment is not mapped [from Apartment]

I have springboot rest appplication with Hibernate and MySQL. I have this error:
nested exception is
org.springframework.dao.InvalidDataAccessApiUsageException:
org.hibernate.hql.internal.ast.QuerySyntaxException: Apartment is not
mapped [from Apartment]
But I dont know where I have a mistake. I have two tables: Apartments and Residents in DB. But now I try only getAllApartments() method. I use Intellij and I even checked my DB in her. And I have little picture near my Entity class, where I have correct data source. And I think that I checked names my class and fields.
This is my Entity:
#Entity
#Table(name = "Apartments")
public class Apartment {
#Column(name = "apartment_id")
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer apartmentId;
#Column(name = "apartment_number"
private Integer apartmentNumber;
#Column(name = "apartment_class")
private String apartmentClass;
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH},
mappedBy = "apartment")
List<Resident> residentList;
My DAO method:
#Repository
public class ApartmentDAOImpl implements ApartmentDAO {
#Autowired
private EntityManager entityManager;
#Override
public List<Apartment> getAllApartment() {
Session session = entityManager.unwrap(Session.class);
Query query = session.createQuery("from Apartment");
List<Apartment> apartmentList = query.getResultList();
return apartmentList;
}
My Controller:
#RestController
#RequestMapping("/api")
public class ApartmentController {
#Autowired
ApartmentService apartmentService;
#GetMapping("/apartments")
public List<Apartment> getAllApartments() {
List<Apartment> apartmentList = apartmentService.getAllApartment();
return apartmentList;
}
I also have service layer without any logic.
My property.file
spring.datasource.url=jdbc:mysql://localhost:3306/correct_db?useSSL=false&serverTimezone=UTC
spring.datasource.username=projuser
spring.datasource.password=projuser
Give me advice, please.
Maybe, As I used multi module application, Hibernate or Spring didn't see my Entity.
And I clearly indicated my Entity class with #EntityScan(basePackages = {"com.punko.entity"}) under my SpringBootApplication class:
#SpringBootApplication(scanBasePackages = "com.punko")
#EntityScan(basePackages = {"com.punko.entity"})
public class SpringBootApplicationConfig {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplicationConfig.class, args);
}

Spring MVC Transactional in dao service and controller layers

I'm using Spring MVC with Spring data.
Simple example of my problem:
My dao Service class:
#Service
#AllArgsConstructor
#Transactional
public class FooService{
private FooRepository fooRepo;
public Foo save(Foo foo){
return fooRepo.save(foo);
}
}
and controller:
#Controller
#AllArgsConstructor
#Transactional //if I remove this, method add does not save a foo.
//But I don't understand why, because FooService already has #Transactional annotation
public class FooController{
private FooService fooService;
#PostMapping("/add")
public String add(#RequestParam("programName") String programName, #RequestParam("id") long id){
Foo foo = fooService.findById(id).get();
foo.setProgramName(programName);
fooService.save(foo);
return "somePage";
}
}
If I remove #Transaction annotation from controller class, method save will not update foo object.
And I don't understand why I should mark controller by #Transactional annotation if I already mark service class by this annotation?
############ UPDATE ####################
Simple detailed description:
I have Program and Education entities. One Program has many Education, Education entity has foreign key program_id.
There is a page with Program form, there are fields: program id, program theme,..., and field with a list of education id separated by commas.
I'm trying to update the education list at the program, so I add a new education id at the page form and click save. Through debugger I see, that new education has appeared in the program, but changes do not appear in the database.
#Controller
#RequestMapping("/admin/program")
#AllArgsConstructor //this is lombok, all services autowired by lombok with through constructor parameters
#Transactional//if I remove this, method add does not save a foo.
//But I don't understand why, because FooService already has #Transactional annotation
public class AdminProgramController {
private final ProgramService programService;
private final EducationService educationService;
#PostMapping("/add")
public String add(#RequestParam("themeName") String themeName, #RequestParam("orderIndex") int orderIndex,
#RequestParam(value = "educationList", defaultValue = "") String educationList,
#RequestParam(value = "practicalTestId") long practicalTestId){
saveProgram(themeName, orderIndex, educationList, practicalTestId);
return "adminProgramAdd";
private Program saveProgram(long programId, String themeName, int orderIndex, String educationList, long practicalTestId){
List<Long> longEducationList = Util.longParseEducationList(parsedEducationList); //this is list of Education id separeted by commas that I load from page form
//creating new program and set data from page form
Program program = new Program();
program.setId(programId);
program.setThemeName(themeName);
program.setOrderIndex(orderIndex);
//starting loop by education id list
longEducationList.stream()
.map(educationRepo::findById)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(edu->{
//linking program and education
program.getEducationList().add(edu);
edu.setProgram(program);
});
//saving new program or updating by service if there is one already
Program savedProgram = programService.save(program);
//saving education with updated program
for(Education edu : savedProgram.getEducationList())
{
educationService.save(edu);
}
return savedProgram;
}
}
ProgramService:
#Service
#AllArgsConstructor //this is lombok, all services autowired by lombok with throught constructor parameters
#Transactional
public class ProgramService {
private ProgramRepo programRepo;
//other code here.....
public Program save(Program program) {
Optional<Program> programOpt = programRepo.findById(program.getId());
//checking if the program is already exist, then update it paramateres
if(programOpt.isPresent()){
Program prgm = programOpt.get();
prgm.setThemeName(program.getThemeName());
prgm.setOrderIndex(program.getOrderIndex());
prgm.setPracticalTest(program.getPracticalTest());
prgm.setEducationList(program.getEducationList());
return programRepo.save(prgm);
}
//if not exist then just save new program
else{
return programRepo.save(program);
}
}
}
Education service
#Service
#AllArgsConstructor //this is lombok, all services autowired by lombok with throught constructor parameters
#Transactional
public class EducationService {
private EducationRepo educationRepo;
//other code here....
public Education save(Education education){
return educationRepo.save(education);
}
}
Program entity:
#Entity
#ToString(exclude = {"myUserList", "educationList", "practicalTest"})
#Getter
#Setter
#NoArgsConstructor
public class Program implements Comparable<Program>{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "theme_name")
private String themeName;
#Column(name = "order_index")
private int orderIndex; //from 1 to infinity
#OneToMany(mappedBy = "program", fetch = FetchType.LAZY)
#OrderBy("orderIndex asc")
private List<Education> educationList = new ArrayList<>();
#OneToMany(mappedBy = "program", fetch = FetchType.LAZY)
private List<MyUser> myUserList = new ArrayList<>();
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "test_id")
private PracticalTest practicalTest;
public Program(int orderIndex, String themeName) {
this.orderIndex = orderIndex;
this.themeName = themeName;
}
public Program(long id) {
this.id = id;
}
//other code here....
}
Education entity:
#Entity
#ToString(exclude = {"program", "myUserList"})
#Getter
#Setter
#NoArgsConstructor
public class Education implements Comparable<Education>{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String link;
#Column(name = "order_index")
private int orderIndex;
private String type;
private String task;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "program_id")
private Program program;
#OneToMany(mappedBy = "education", fetch = FetchType.LAZY)
private List<MyUser> myUserList = new ArrayList<>();
public Education(String link, int orderIndex, String task, Program program) {
this.link = link;
this.orderIndex = orderIndex;
this.task = task;
this.program = program;
}
//other code here....
}
Program repo:
#Repository
public interface ProgramRepo extends CrudRepository<Program, Long> {
Optional<Program> findByPracticalTest(PracticalTest practicalTest);
Optional<Program> findByOrderIndex(int orderIndex);
List<Program> findByIdBetween(long start, long end);
}
Education repo:
#Repository
public interface EducationRepo extends CrudRepository<Education, Long> {
Optional<Education> findByProgramAndOrderIndex(Program program, int orderIndex);
#Query("select MAX(e.orderIndex) from Education e where e.program.id = ?1")
int findLastEducationIndexByProgramId(long programId);
}
I think the problem is program object created in one transaction and saved in another. That's why if I put Transactional on controller it works. There are two ways to solve the problem:
Without transactional on the controller: then I must save education object at first, because it has program id field and then save the program object.
With transactional on controller: then saving order has no matter, because saving object occurs in one transaction

Hibernate - Mapping three tables with a single save

I am trying to create a project that will use Hibernate to store the objects to the database.
If I simply insert (save) an object that does not contain a mapping with another table everything works fine. However, I have a case where there is a connection between three tables. The tables are the Asset, MonetaryValue and CurrencyType (see below).
When an Asset is inserted, the monetaryValueType must be provided (by the user ) along with the currency type. Asset holds a OneToOne relation with the MonetaryValueType and MonetaryValueType holds a OneToOne relation to the CurrencyType Table.
More specifically, below you will find the database tables.
Asset(asset_id,ownerIID,valueID,samID), where valueID is the foreign key to the MonetaryValueType Table (OneToOne undirectional mapping)
MonetaryValueType(mvID, mValue,currencyId), where currencyID is the foreign key to the CurrencyType Table (OneToOne undirectional mapping)
CurrencyType(currencyID,currField,currValue,currSymbol).
The problem is that every time I create the asset object and I am calling the asset service to save the element, Hibernate either create a select query that tries to select from a database table I did never define or Inserts in the currency field with wrong column names (i.e. currency_field instead of currField etc.)
I've tried to play with all the Cascade types but nothing seems to work.
Asset.java
#Entity
#Table(name="asset")
public class Asset implements java.io.Serializable{
#Id
#Column(name="assetID", unique = true, nullable = false)
private long assetID;
#Column(name="ownerID")
private long ownerID;
#OneToOne
#JoinColumn(name="valueID")
private MonetaryValueType monetaryValueType;
#Column(name="samID")
private long samID;
------------Constructor, Getters , Setters-----
MonetaryValueType.java
#Entity
#Table(name="monetaryvaluetype")
public class MonetaryValueType{
#Id
#Column(name="mvID",nullable = false,unique = true)
private Long id;
#Column(name="mValue")
private double mValue;
#OneToOne
#JoinColumn(name="currencyId")
private CurrencyType currency;
------------Constructor, Getters , Setters-----
CurrencyType.java
#Entity
#Table(name="currencytype")
public class CurrencyType implements java.io.Serializable {
#Id
#Column(name="currencyID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int currencyID;
#Column(name="currField")
private String currField;
#Column(name="currValue")
private String currValue;
#Column(name="currSymbol")
private String currSymbol;
------------Constructor, Getters , Setters-----
Every entity holds its own DAO,DAOImpl, Service and ServiceImpl class. For instance, for the asset class the DAOImpl and ServiceImpl can be found below:
AssetDAOImpl.java
#Repository
public class AssetDAOImpl implements AssetDAO{
private Logger logger = LoggerFactory.getLogger(this.getClass());
//entity manager field
#Autowired
private EntityManager entityManager;
#Override
public List<Asset> findAll() {
Session currentSession = entityManager.unwrap(Session.class);
//create a query
Query theQuery =
currentSession.createQuery("from asset",Asset.class);
//execute query and get result list
List<Asset> aModelElements = theQuery.getResultList();
//return the results
return aModelElements;
}
#Override
public Asset findById(int theId) {
return null;
}
#Override
public Asset insert(Asset assetElement) {
//Session currentSession = entityManager.unwrap(Session.class);
boolean success = false;
try {
entityManager.persist(assetElement);
logger.info("Asset -> {}", assetElement);
return assetElement;
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
AssetServiceImpl.java
#Service
public class AssetServiceImpl implements AssetService {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private AssetDAO assetDAO;
#Autowired
public AssetServiceImpl(AssetDAO theAssetDAO){
assetDAO=theAssetDAO;
}
#Override
#Transactional
public List<Asset> findAll() {
return assetDAO.findAll();
}
#Override
#Transactional
public Asset findById(int theId) {
return assetDAO.findById(theId);
}
#Override
#Transactional
public Asset insert(Asset theAsset) {
assetDAO.insert(theAsset);
return theAsset;
}
...
The class that I use to fill the asset class (and all its children) is:
UniqueIDGenerator uniqueIDGenerator = new UniqueIDGenerator();
CurrencyType currencyType = new CurrencyType();
Asset asset = new Asset();
MonetaryValueType monetaryValueType = new MonetaryValueType();
currencyType.setCurrValue(ctx.value().monetaryValueType().currency().CurrencyType().getText());
currencyType.setCurrSymbol("currency");
monetaryValueType.setId(uniqueIDGenerator.nextId());
monetaryValueType.setmValue(Double.parseDouble(ctx.value().monetaryValueType().mValue().getText()));
monetaryValueType.setCurrency(currencyType);
asset.setMonetaryValueType(monetaryValueType);
asset.setAssetID(uniqueIDGenerator.nextId());
asset.setOwner(uniqueIDGenerator.nextId());
asset.setSamID(uniqueIDGenerator.nextId());
assetService.insert(asset);
Whenever I call the class mentioned above, I get the following error:
Hibernate:
insert
into
element1
(datefrom, dateto, description, name, statusid, samid)
values
(?, ?, ?, ?, ?, ?)
2019-08-05 20:19:00 INFO MyClass:63 - the result is:true
Hibernate:
select
monetaryva_.mvid,
monetaryva_.currency_id as currency3_57_,
monetaryva_.m_value as m_value2_57_
from
monetaryvaluetype monetaryva_
where
monetaryva_.mvid=?
2019-08-05 20:19:01.084 WARN 56712 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22
2019-08-05 20:19:01.084 ERROR 56712 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'monetaryva_.currency_id' in 'field list'
As you can see, hibernate created columns (currency_id instead of currencyID) that are not in accordance with my database tables even though I used the #Column annotation.
Use following two lines in your application.properties file
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

JPA - How to query using Specification and #EmbeddedId?

I'm using a JPA query that uses a specification to retrieve entities. When I execute the query, I'm getting the error:
org.springframework.data.mapping.PropertyReferenceException: No property name found for type Task!
I've looked at the answers to similar questions that have been asked on this site previously & tried to model my code to follow the patterns that were recommended but the code is still failing.
When I step through the code with a debugger, the expanded path in the criteria builder is returning the embedded ID class, but when the specification is actually used in the query it looks like the attribute is being applied to the base entity class.
Am I missing something obvious?
Here is the entity class:
#Entity
#Table(name = "TASKS")
public class Task implements Serializable {
#EmbeddedId
private TaskId id;
...more attributes, getters and setters
}
Here is the embedded ID entity class:
#Embeddable
public class TaskId implements Serializable {
#Column(name = "NAME", length = 100)
private String name;
...more attributes, getters and setters
}
Here is the specification builder that matches on the embedded id 'name' attribute:
public class HasTaskNameSpec {
private HasTaskNameSpec() {
}
public static Specification<Task> equals(String name) {
return (root, query, criteriaBuilder) -> {
return criteriaBuilder.equal(root.get("id").get("name"), taskName);
};
}
}
The query is executed on the repository as follows:
List<Task> results = taskRepository.findAll(HasTaskNameSpec.equals("foo"));
The repository itself is very simple:
public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
List<Task> findByIdName(String name);
Page<Task> findByIdName(String name, Pageable page);
}
** EDIT added methods to repository as was suggested below **
Ahh, the root cause was totally in our codebase. There was a sort order being specified on the page that didn't include the embedded "id" attribute. The above code works.
'root.get({embeddedIdName}).get({subPropertyName})' is used to query on embeddedId using specification.
#Embeddable
public class ProjectId implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name = "PROJECT_NAME")
private String projectName;
#Column(name = "ORGANIZATION")
private String organization;
......
......
}
#Entity
#Table(name = "projects")
public class Project {
#EmbeddedId
private ProjectId projectId;
#Column(name = "STARTED_TIME")
private Timestamp startedTime;
#Column(name = "ACTIVE")
private String active;
#Column(name = "DESCRIPTION")
private String description;
......
......
}
In the above snippet, ProjectId is an embedded id. To query on projectName, we should use below snippet.
expression = root.get("projectId").get("projectName");
Demo application link.
Take a look at this link which has a similar query.
EmbbededId Lookup
The final answer suggests that you can add a method to your TaskRepository thus.
public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
public List<Task> findByIdName(String name);
}

How hibernate retrieve data from existing database view?

I'm new to hibernate. My problem is that I have an Oracle database. I have a view in the database. Now I want to use hibernate to retrieve data in that view. Is there any possible solutions?
Below Snippet can solve your problem, which has been extracted from the tutorial: Mapping Hibernate Entities to Views
Database Query
CREATE OR REPLACE VIEW cameron AS
SELECT last_name AS surname
FROM author
WHERE first_name = 'Cameron';
view entity
#Entity
#NamedNativeQuery(name = "findUniqueCameronsInOrder", query = "select * from cameron order by surname", resultClass = Cameron.class)
public class Cameron implements java.io.Serializable {
private static final long serialVersionUID = 8765016103450361311L;
private String surname;
#Id
#Column(name = "SURNAME", nullable = false, length = 50)
public String getSurname() {
return surname;
}
public void setSurname(final String surname) {
this.surname = surname;
}
}
Hibernate mapping file.
<mapping class="examples.hibernate.spring.query.domain.Cameron" />
finally some test !...
#Test
public void findTheCameronsInTheView() throws Exception {
final List<Cameron> camerons = findUniqueCameronsInOrder();
assertEquals(2, camerons.size());
final Cameron judd = camerons.get(0);
final Cameron mcKenzie = camerons.get(1);
assertEquals("Judd", judd.getSurname());
assertEquals("McKenzie", mcKenzie.getSurname());
}
A view is from accessing data nothing different from table, a problem arises when you want to add,update or delete from view.
Please read http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/querysql.html
It' very similar to mapping ordinary database table.
Create an Entity and use your view name as Table name.
#Entity
#Table(name = "rc_latest_offer_details_view")
public class OfferLatestDetailsViewEntity {
#Id
#Column(name = "FK_OFFER_ID")
private int offerId;
#Column(name = "MAX_CHANGED_DTM")
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime changedDateTime;
private BigDecimal price;
...
}
Then query for entities same way as you do for normal table.
Working in Hibernate 4, Spring 4.
we can achieve this by using # Immutable annotation in entity class to map database view with Hibernate
For example : I have created one database view user_data which have 2 columns (id and name) and mapped user_data view in the same way as database tables.
#Entity
#Table(name = "user_data")
#Immutable
public class UserView {
#Id
#Column(name = "ID")
private int ID ;
#Column(name = "NAME")
private String name ;
}

Categories

Resources