Generate UUID key using CypherdslStatementExecutor - spring

I am using neo4j-cypher-dsl-codegen-sdn6 to generate a static model to use in Cypher-DSL.
This is my source #Node
#Node
class Person(
#Id
#GeneratedValue(GeneratedValue.UUIDGenerator::class)
var id: UUID?,
val name: String,
var born: Int
) {
#JsonCreator
constructor(#JsonProperty("name") name: String, #JsonProperty("born") born: Int) : this(null, name, born) {
}
}
Generated static model
#Generated(
value = "org.neo4j.cypherdsl.codegen.core.NodeImplBuilder",
date = "2022-03-03T14:26:04.213265104+02:00",
comments = "This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration."
)
public final class Person_ extends NodeBase<Person_> {
public static final Person_ PERSON = new Person_();
public final Property ID = this.property("id");
public final Property NAME = this.property("name");
public final Property BORN = this.property("born");
public Person_() {
super("Person");
}
private Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {
super(symbolicName, labels, properties);
}
#Override
public Person_ named(SymbolicName newSymbolicName) {
return new Person_(newSymbolicName, getLabels(), getProperties());
}
#Override
public Person_ withProperties(MapExpression newProperties) {
return new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));
}
}
Repository
interface PeopleRepository : Neo4jRepository<Person, UUID>, CypherdslStatementExecutor<Person?>
Failing test
#Test
fun createPerson(#Autowired peopleRepository: PeopleRepository) {
val person: Person_ = Person_.PERSON.withProperties(
Person_.PERSON.NAME, Cypher.literalOf<String>("Micheal"),
Person_.PERSON.BORN, Cypher.literalOf<Int>(1999)
)
val result: Optional<Person?> = peopleRepository.findOne(Cypher.create(person).returning(person).build())
assertNotNull(result.get().id)
}
I would have expected that the UUID gets generated.
Please can someone try to replicate this error, or advise if there is another way to generate the UUID.

Related

identifier of an instance of ...was altered from

i found many response about this title "identifier of an instance of ...was altered from ..." but none of this give me a solution.
i am using PostgreSQL
with just 2 column id_type and libelle.
here is my Model level :
package com.stev.pillecons.pilleCons.models;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
#Entity(name = "type_pille")
#JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class LePille {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private int id_type;
private String libelle;
public LePille(){}
public String getLibelle() {
return libelle;
}
public void setLibelle(String libelle) {
this.libelle = libelle;
}
public int getId_type() {
return id_type;
}
public void setId_type(int id_type) {
this.id_type = id_type;
}
}
My Service level :
#Override
public LePille updatePille(Integer id, LePille Sourcepille) {
Optional<LePille> existingSession = pilleRepo.findById(id);
if (existingSession.isPresent())
{
LePille Targetpile = existingSession.get();
BeanUtils.copyProperties(Sourcepille, Targetpile);
return pilleRepo.saveAndFlush(Targetpile);
}
else
{
throw new PilleException("pille not found");
}
}
when i debug it, with the data
{"id_type":10,"libelle":"dsf"}
with postman
the value of TargetPille is : {"id_type":10,"libelle":"dsf"}
and the value of SourcePille : {"id_type":0,"libelle":"popo"}
last but not least is Controller level:
#RequestMapping(value = "{id}", method = RequestMethod.PUT)
public ResponseEntity update(#PathVariable Integer id, #RequestBody LePille session) {
LePille updPille = pilleService.updatePille(id, session);
return new ResponseEntity<LePille>(updPille, HttpStatus.OK);
}
it is strange because juste update that not working, Create, Read and Delete works fine.
thanks in advance
i just change the code like this:
BeanUtils.copyProperties(Sourcepille, Targetpile, "id_type");
just add the id_type to ignore variable

Why might Room database IDs all show as 0 in a log/Toast message?

I'm trying to get the id of the last inserted object into a database using Room with Android. I can fetch the last object using an SQL query and can call other methods to get the various properties of that object which the user has set when saving the object. But getId() always returns 0. When I examine the table contents in Android Studio's app inspector, I can clearly see that Room is generating a unique primary key for each row, but I just can't get at it. Can anyone suggest what the problem might be?
Here's the Dao query:
#Query("SELECT * FROM gamebooks_table WHERE gamebookId=gamebookId ORDER BY gamebookId DESC LIMIT 1")
LiveData<Gamebook> getSingleGamebookByID();
And here's the annotated entity class:
#Entity(tableName = "gamebooks_table")
public class Gamebook {
#PrimaryKey(autoGenerate = true)
private long gamebookId;
private String gamebookName;
private String gamebookComment;
private String gamebookPublisher;
private float gamebookStarRating;
public Gamebook(String gamebookName, String gamebookComment, String gamebookPublisher, float gamebookStarRating) {
this.gamebookName = gamebookName;
this.gamebookComment = gamebookComment;
this.gamebookPublisher = gamebookPublisher;
this.gamebookStarRating = gamebookStarRating;
}
public long getGamebookId() {
return gamebookId;
}
public String getGamebookName() {
return gamebookName;
}
public String getGamebookComment() {
return gamebookComment;
}
public String getGamebookPublisher() {
return gamebookPublisher;
}
public float getGamebookStarRating(){
return gamebookStarRating;
}
public void setGamebookId(long gamebookId) {
this.gamebookId = gamebookId;
}
}
SOLVED
Finally sorted this by adding an Observer to my DAO method which returns a single gamebook. Within the Observer's onChanged() method, I can loop through all Gamebooks in the LiveData List (even though there's only one because I'm limiting it to one in the SQL query) and call getId() to get their respective IDs.
mainViewModel.getSingleGamebook().observe(this, new Observer<List<Gamebook>>() {
#Override
public void onChanged(List<Gamebook> gamebooks) {
int i=0;
for(Gamebook gamebook : gamebooks){
gamebookId= gamebook.getGamebookId();
Log.d(TAG, "Gamebook Name: "+gamebook.getGamebookName()+ " Database ID: " +gamebookId);
i++;
}
}
});
I believe that your issue is due to the only constructor being available not setting the id so the LiveData uses the default value of 0 for a long.
I'd suggest having a default constructor and thus all setters/getters and (optionally) using #Ignore annotation for one of the constructors..
without #Ignore you get warnings Gamebook.java:8: warning: There are multiple good constructors and Room will pick the no-arg constructor. You can use the #Ignore annotation to eliminate unwanted constructors. public class Gamebook {
e.g. :-
#Entity(tableName = "gamebooks_table")
public class Gamebook {
#PrimaryKey(autoGenerate = true)
private long gamebookId;
private String gamebookName;
private String gamebookComment;
private String gamebookPublisher;
private float gamebookStarRating;
public Gamebook(){} /*<<<<< ADDED */
#Ignore /*<<<<< ADDED - is not required - could be on the default constructor but not both*/
public Gamebook(String gamebookName, String gamebookComment, String gamebookPublisher, float gamebookStarRating) {
this.gamebookName = gamebookName;
this.gamebookComment = gamebookComment;
this.gamebookPublisher = gamebookPublisher;
this.gamebookStarRating = gamebookStarRating;
}
public long getGamebookId() {
return gamebookId;
}
public String getGamebookName() {
return gamebookName;
}
public String getGamebookComment() {
return gamebookComment;
}
public String getGamebookPublisher() {
return gamebookPublisher;
}
public float getGamebookStarRating(){
return gamebookStarRating;
}
public void setGamebookId(long gamebookId) {
this.gamebookId = gamebookId;
}
/* ADDED setters */
public void setGamebookName(String gamebookName) {
this.gamebookName = gamebookName;
}
public void setGamebookComment(String gamebookComment) {
this.gamebookComment = gamebookComment;
}
public void setGamebookPublisher(String gamebookPublisher) {
this.gamebookPublisher = gamebookPublisher;
}
public void setGamebookStarRating(float gamebookStarRating) {
this.gamebookStarRating = gamebookStarRating;
}
}
You also probably want to be able to pass the respective id to the getSingleGamebookByID, so you may wish to change this to:-
#Query("SELECT * FROM gamebooks_table WHERE gamebookId=:gamebookId /*<<<<< ADDED to use id passed */ ORDER BY gamebookId DESC LIMIT 1")
LiveData<Gamebook> getSingleGamebookByID(long gamebookId /*<<<<< ADDED to use id passed */);
you would probably want to remove the comments.
Note the LiveData aspect has not been tested and is conjecture.
Example
This example shows that room is fine with your original code but that the issues is on the LiveData/Viewmodel side :-
public class MainActivity extends AppCompatActivity {
TheDatabase db;
GamebookDao dao;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Note The Database has .allowMainThreadQueries */
db = TheDatabase.getInstance(this);
dao = db.getGamebookDao();
long gb1id = dao.insert(new Gamebook("Gamebook1","blah","Gamebook1 Publisher", 10.1F));
long gb2id = dao.insert(new Gamebook("Gamebook2","blah","Gamebook2 Publisher", 6.1F));
long gb3id = dao.insert(new Gamebook("Gamebook3","blah","Gamebook3 Publisher", 10.1F));
logGameBook(dao.getSingleGamebookByID());
logGameBook(dao.getSingleGamebookByID());
logGameBook(dao.getSingleGamebookByID());
/* Alternative that allows the ID to be specified */
logGameBook(dao.getSingleGamebookByIDAlternative(gb1id));
logGameBook(dao.getSingleGamebookByIDAlternative(gb2id));
logGameBook(dao.getSingleGamebookByIDAlternative(gb3id));
}
void logGameBook(Gamebook gb) {
Log.d("GAMEBOOKINFO","Gamebook is " + gb.getGamebookName() + " id is " + gb.getGamebookId());
}
}
The above uses your original code, the TheDatabase is a basic #Database annotated class BUT with .allowMainThreadQueries so it is run on the main thread.
The log, after running, includes:-
2022-03-12 08:16:12.556 D/GAMEBOOKINFO: Gamebook is Gamebook3 id is 3
2022-03-12 08:16:12.558 I/chatty: uid=10132(a.a.so71429144javaroomidreturnedaszero) identical 1 line
2022-03-12 08:16:12.561 D/GAMEBOOKINFO: Gamebook is Gamebook3 id is 3
2022-03-12 08:16:12.568 D/GAMEBOOKINFO: Gamebook is Gamebook1 id is 1
2022-03-12 08:16:12.572 D/GAMEBOOKINFO: Gamebook is Gamebook2 id is 2
2022-03-12 08:16:12.574 D/GAMEBOOKINFO: Gamebook is Gamebook3 id is 3
Note how the first just returns the same object and thus id.

Getting Null Values in Spring Native Query Project

This is my Data Repository file and i used native query to retrieve all data address(Locations) of Data. I called the function using Postman and I got null outputs of locations. This my first time of using Native query and its really impossible to solve these errors
DataRepository
public interface DataRepository extends JpaRepository<Data, Long> {
#Query(value = "SELECT dataAddress FROM Data")
List<DataProject> getDataAddress();
}
DataServiceImpl
public List<DataProject> getDataAddress() {
return dataRepository.getDataAddress();
}
DataService
List<DataProject> getDataAddress();
DataModel
#Entity
#Table(name = "CCCData")
public class Data {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long dataId;
#Column(name = "DATA_NAME")
private String dataName;
#Column(name ="DATA_ADDRESS")
private String dataAddress;
#Column(name = "DATA_DESC")
private String dataDesc;
#CreationTimestamp
private Date dateOfCreated;
#CreationTimestamp
private Date dateOfUpdated;
public long getDataId() {
return dataId;
}
public void setDataId(long dataId) {
this.dataId = dataId;
}
public String getDataName() {
return dataName;
}
public void setDataName(String dataName) {
this.dataName = dataName;
}
public String getDataAddress() {
return dataAddress;
}
public void setDataAddress(String dataAddress) {
this.dataAddress = dataAddress;
}
public String getDataDesc() {
return dataDesc;
}
public void setDataDesc(String dataDesc) {
this.dataDesc = dataDesc;
}
public Date getDateOfCreated() {
return dateOfCreated;
}
public void setDateOfCreated(Date dateOfCreated) {
this.dateOfCreated = dateOfCreated;
}
public Date getDateOfUpdated() {
return dateOfUpdated;
}
public void setDateOfUpdated(Date dateOfUpdated) {
this.dateOfUpdated = dateOfUpdated;
}
DataProjection
public interface DataProject {
String getDataAddress();
}
DataController
#GetMapping("/data/locations")
public List<DataProject> getDataAddress() {
return dataService.getDataAddress();
}
Postman Output
[
{
"dataAddress": null
},
{
"dataAddress": null
},
{
"dataAddress": null
},
{
"dataAddress": null
}
]
Spring won't return you only address using below query. It still return you DATA object
public interface DataRepository extends JpaRepository<Data, Long> {
#Query(value = "SELECT dataAddress FROM Data")
List<DataProject> getDataAddress();
}
for fetching only DataAddress you need to create a constructor inside Data model for DataAddress only
public Data(String dataAddress) {
this.dataAddress = dataAddress;
}
and your query will look like this:
public interface DataRepository extends JpaRepository<Data, Long> {
#Query(value = "SELECT new Data(dataAddress) FROM Data")
List<DataProject> getDataAddress();
}
Update 1 :
if you need this for other fields with same datatype and then above 'constructor' based method fails. There are some other alternatives:
You can fetch DATA object and use java stream map function to extract only 1 field. data.stream().map((data) -> data.getDataAddress()).collect(Collectors.toList())
You can use native SQL query to fetch only required fields.
#Query(value = "SELECT d.data_address FROM CCCData d", nativeQuery=true)

How to reference a properties value inside the schema attribute of an entity?

There is an entity :
#Entity
#Table(name = "ITMMASTER" , schema = "TOMCTB")
public class Article {
#Id
#Column(name = "ITMREF_0")
private String code_article;
#Column(name = "ACCCOD_0")
private String acccod;
public String getCode_article() {
return code_article;
}
public void setCode_article(String code) {
this.code_article = code;
}
public String getAcccod() {
return acccod;
}
public void setAcccod(String acccod) {
this.acccod = acccod;
}
}
I want to make the schema attribute to be dynamic depending on a properties file property value , for example : env.schema = TOMEXPL.
How to achieve that ?
I didn't tried it but I guess this should work.
public class DynamicNamingStrategy extends DefaultNamingStrategy {
#Value("db.table.name")
private String name;
#Override
public String tableName(String tableName) {
return name;
}
...
}
SessionFactory sessionFactory;
Configuration config = new AnnotationConfiguration()
.configure("hibernate.cfg.xml")
.setNamingStrategy( new DynamicNamingStrategy() );
sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();

Dynamic MongoDB collection in spring boot

I want to create a MongoDB collection for each month dynamically.
Example: viewLog_01_2018, viewLog_02_2018
#Document(collection = "#{viewLogRepositoryImpl.getCollectionName()}")
#CompoundIndexes({
#CompoundIndex(def = "{'viewer':1, 'viewed':1}", name = "viewerViewedIndex",unique=true)
})
public class ViewLog {
private Integer viewer;
private Integer viewed;
private Date time;
public Integer getViewer() {
return viewer;
}
public void setViewer(Integer viewer) {
this.viewer = viewer;
}
public Integer getViewed() {
return viewed;
}
public void setViewed(Integer viewed) {
this.viewed = viewed;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}
The implementation for the collection name is as follows:
#Repository
public class ViewLogRepositoryImpl implements ViewLogRepositoryCustom {
private String collectionName;
public ViewLogRepositoryImpl() {
CommonUtility common = new CommonUtility();
Pair<Integer, Integer> pair = common.getStartingEndingDateOfMonth();
setCollectionName("viewLog_"+pair.getFirst()+"_"+pair.getSecond());
}
#Override
public String getCollectionName() {
return collectionName;
}
#Override
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
}
On my each request, to save a document, I am setting the collection name as:
#Autowired
ViewLogRepository viewLogRepository;
public boolean createLog(int viewer, int viewed,String viewed_mmm, Date time){
CommonUtility common = new CommonUtility();
Pair<Integer, Integer> pair = common.getStartingEndingDateOfMonth();
viewLogRepository.setCollectionName("viewLog_"+pair.getFirst()+"_"+pair.getSecond());
ViewLog viewLog = new ViewLog();
viewLog.setViewer(viewer);
viewLog.setViewed(viewed);
viewLog.setTime(time);
ViewLog viewLog2 = viewLogRepository.save(viewLog);
return true;
}
The problem I am facing is that I when for the first time I up my service the mongo collection that is created has the unique attribute for the fields 'viewer' and 'viewed' but for any subsequent collection that is created dynamically, the document does not have the unique constraint and multiple entries of same viewer-viewed combination are able to be inserted.
Any help will be very much appreciated.

Resources