JPA question (Scala using) - database

OpenJPA and Scala question.
There are 2 tables in database (h2) - tasks and taskLists.
TaskList contains collection ArrayList.
Each TaskList can contain tasks from another TaskLists
When taskX modified in TaskList1 it have to be modified in TaskList2, if it contains taskX.
How to implement this?
I can add new task to task list and save it to DB, but when I try to add taskX from TaskList1 tasks collection to TaskList2 tasks collection and persist it, taskX is not persisted in db.
Example:
1. Adding task1 to taskList1 and task2 to taskList2 will result:
TaskList1: [task1]
TaskList2: [task2]
2. Adding task2 to taskList1 will result:
TaskList1: [task1]
3. Adding task3 to taskList1 and task4 to taskList2 will result:
TaskList1: [task1, task3]
TaskList2: [task2, task4]
What is wrong?
Task class:
import _root_.javax.persistence._
import org.apache.openjpa.persistence._
#Entity
#Table(name="tasks")
#ManyToMany
class CTask (name: String) {
def this() = this("new task")
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
var id: Int = _
var title: String = name
def getId = id
def getTitle = title
def setTitle(titleToBeSet: String) = title = titleToBeSet
override def toString: String = title
}
TaskList class:
import _root_.javax.persistence._
import _root_.java.util.ArrayList
import org.apache.openjpa.persistence._
#Entity
#Table(name="tasklists")
class CTaskList(titleText: String) {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
var id: Int = _
#Column(nullable = false)
var title: String = titleText
#ManyToMany
var tasks: ArrayList[CTask] = _;
var tags: String = ""
var rank: Int = 0
def getTasks = tasks
def this() = this("new task list")
def createTasks: ArrayList[CTask] = {
tasks = new ArrayList[CTask]
tasks
}
def getID = id
def getTags = tags
def setTags(tagsParam: String) = tags = tagsParam
def getRank = rank
def setRank(rankParam: Int) = rank = rankParam
def getTitle: String = title
def getTaskById(index: Int): CTask = {
null
}
def equals(anotherTaskList: CTaskList): Boolean = {
if (anotherTaskList == null) return false
if (anotherTaskList.getTasks == null)
return id == anotherTaskList.getID && title == anotherTaskList.getTitle && tags == anotherTaskList.getTags && rank == anotherTaskList.getRank && tasks == null;
else
return id == anotherTaskList.getID && title == anotherTaskList.getTitle && tags == anotherTaskList.getTags && rank == anotherTaskList.getRank && tasks != null && tasks.size == anotherTaskList.getTasks.size
}
def addTask(taskToBeAdded: CTask): Int = {
if (tasks == null)
tasks = new ArrayList[CTask]
tasks.add(taskToBeAdded)
tasks.indexOf(taskToBeAdded)}
def printTasks = println("TaskList's " + this + " tasks: " + tasks)
}

As far as I know, Many-To-Many association (as specified in your mapping annotations) implies association table between two entities (i.e. #JoinTable annotation should be specified).

Related

Gatling scala - Unable to replace session variable in the request URI

I do have a session variable named AuctionId and couldn't replace AuctionId here in the POST request URI. Can you please advise what I am missing here?
object BidSubmission extends HttpUtil {
val orders_feeder = csv("data/Round-1.csv").circular
def orderSubmission: ChainBuilder =
pause(pauseBy(5) seconds)
.repeat(1) {
feed(orders_feeder)
.exec(postToUri("${Constants.orderSubmission_URL}/#{AuctionId}/base-orders/proxy-bid", "")
.queryParam("employeeId", "#{empNo}")
.body(StringBody(session => {
println(session)
println(session.attributes("empNo"))
val empNo = session.attributes("empNo").asInstanceOf[String]
val orderNo = session.attributes("orderNo").asInstanceOf[String]
println(s"\n\n\n $orderNo \n\n\n")
println("\n\n\n ${Constants.bidSubmission_URL}/#{AuctionId}/base-auctions/proxy-
bid \n\n\n")
var slotNos = orderNo.replace("[", "").replace("]", "").split(" +")
println(s"\n\n\n ${generatePayload(empNo, slotNos)} \n\n\n")
generatePayload(empNo, slotNos)
" "
}))
)
}
it prints uri like this instead of replacing AuctionId with the session variable value- https://order.com/golden/base-auction/system-override/auctions/#{AuctionId}/base-auctions/proxy-bid
trait HttpUtil extends StrictLogging {
def postToUri(uri: String, requestName: String, statusCode: Int = 201): HttpRequestBuilder = {
appendHeaders(http(requestName).post(uri)).check(status.is(statusCode))
}
private def appendHeaders(request: HttpRequestBuilder,
authScheme: String = config.auth.plannerToken): HttpRequestBuilder = {
request
.header("Authorization", authScheme)
.header("Content-Type", "application/json")
.header("Accept", "application/prs.hal-forms+json")
}
}

Trying to display name of users on support action bar

Please i am new to kotlin and i have been trying to retrive the fullname of my users in the data base after using getStringExtra so i can use each of them for the title of my support action bar but the value it returns an empty value.
val name = intent.getStringExtra("fullname")
val receiverUid = intent.getStringExtra("uid")
val senderUid = FirebaseAuth.getInstance().currentUser?.uid
mDbRef = FirebaseDatabase.getInstance().getReference()
senderRoom = receiverUid + senderUid
receiverRoom = senderUid + receiverUid
supportActionBar?.title = name
Here is how i am sending name and receiverUid to my database
sendButton.setOnClickListener{
val message = messageBox.text.toString()
val messageObject = Message(message, senderUid)
val name = name.toString()
val receiverUid = receiverUid.toString()
val chatlistObject = ModelChatList(name, message, receiverUid)
mDbRef.child("chats").child(senderRoom!!).child("messages").push()
.setValue(messageObject).addOnSuccessListener {
mDbRef.child("chats").child(receiverRoom!!).child("messages").push()
.setValue(messageObject).addOnSuccessListener {
mDbRef.child("Chatlist").push().setValue(chatlistObject)
}
}
messageBox.setText("")
But when i try to retrive my ModelChatlist object it returns only two values leaving out the receivername as shown in the ModelChatlist below
class ModelChatList {
private var receivername:String = ""
private var lastmessage:String = ""
private var uid:String = ""
constructor(){}
constructor(receivername: String, lastmessage:String, uid:String){
this.receivername = receivername
this.lastmessage = lastmessage
this.uid =uid
}
fun getReceivername(): String{
return receivername
}
fun setReceivername(receivername: String){
this.receivername= receivername
}
fun getUid(): String{
return uid
}
fun setUid(uid: String){
this.uid= uid
}
fun getLastmessage(): String{
return lastmessage
}
fun setLastmessage(lastmessage: String){
this.lastmessage= lastmessage
}
}
In case you are wondering, "fullname" is in my database as the name the users enter when they sign up. Thank You

I want to write ORC file using Flink's Streaming File Sink but it doesn’t write files correctly

I am reading data from Kafka and trying to write it to the HDFS file system in ORC format. I have used the below link reference from their official website. But I can see that Flink write exact same content for all data and make so many files and all files are ok 103KB
https://ci.apache.org/projects/flink/flink-docs-release-1.11/dev/connectors/streamfile_sink.html#orc-format
Please find my code below.
object BeaconBatchIngest extends StreamingBase {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
def getTopicConfig(configs: List[Config]): Map[String, String] = (for (config: Config <- configs) yield (config.getString("sourceTopic"), config.getString("destinationTopic"))).toMap
def setKafkaConfig():Unit ={
val kafkaParams = new Properties()
kafkaParams.setProperty("bootstrap.servers","")
kafkaParams.setProperty("zookeeper.connect","")
kafkaParams.setProperty("group.id", DEFAULT_KAFKA_GROUP_ID)
kafkaParams.setProperty("auto.offset.reset", "latest")
val kafka_consumer:FlinkKafkaConsumer[String] = new FlinkKafkaConsumer[String]("sourceTopics", new SimpleStringSchema(),kafkaParams)
kafka_consumer.setStartFromLatest()
val stream: DataStream[DataParse] = env.addSource(kafka_consumer).map(new temp)
val schema: String = "struct<_col0:string,_col1:bigint,_col2:string,_col3:string,_col4:string>"
val writerProperties = new Properties()
writerProperties.setProperty("orc.compress", "ZLIB")
val writerFactory = new OrcBulkWriterFactory(new PersonVectorizer(schema),writerProperties,new org.apache.hadoop.conf.Configuration);
val sink: StreamingFileSink[DataParse] = StreamingFileSink
.forBulkFormat(new Path("hdfs://warehousestore/hive/warehouse/metrics_test.db/upp_raw_prod/hour=1/"), writerFactory)
.build()
stream.addSink(sink)
}
def main(args: Array[String]): Unit = {
setKafkaConfig()
env.enableCheckpointing(5000)
env.execute("Kafka_Flink_HIVE")
}
}
class temp extends MapFunction[String,DataParse]{
override def map(record: String): DataParse = {
new DataParse(record)
}
}
class DataParse(data : String){
val parsedJason = parse(data)
val timestamp = compact(render(parsedJason \ "timestamp")).replaceAll("\"", "").toLong
val event = compact(render(parsedJason \ "event")).replaceAll("\"", "")
val source_id = compact(render(parsedJason \ "source_id")).replaceAll("\"", "")
val app = compact(render(parsedJason \ "app")).replaceAll("\"", "")
val json = data
}
class PersonVectorizer(schema: String) extends Vectorizer[DataParse](schema) {
override def vectorize(element: DataParse, batch: VectorizedRowBatch): Unit = {
val eventColVector = batch.cols(0).asInstanceOf[BytesColumnVector]
val timeColVector = batch.cols(1).asInstanceOf[LongColumnVector]
val sourceIdColVector = batch.cols(2).asInstanceOf[BytesColumnVector]
val appColVector = batch.cols(3).asInstanceOf[BytesColumnVector]
val jsonColVector = batch.cols(4).asInstanceOf[BytesColumnVector]
timeColVector.vector(batch.size + 1) = element.timestamp
eventColVector.setVal(batch.size + 1, element.event.getBytes(StandardCharsets.UTF_8))
sourceIdColVector.setVal(batch.size + 1, element.source_id.getBytes(StandardCharsets.UTF_8))
appColVector.setVal(batch.size + 1, element.app.getBytes(StandardCharsets.UTF_8))
jsonColVector.setVal(batch.size + 1, element.json.getBytes(StandardCharsets.UTF_8))
}
}
With bulk formats (such as ORC), the StreamingFileSink rolls over to new files with every checkpoint. If you reduce the checkpointing interval (currently 5 seconds), it won't write so many files.

Slick 3 join query one to many relationship

Imagine the following relation
One book consists of many chapters, a chapter belongs to exactly one book. Classical one to many relation.
I modeled it as this:
case class Book(id: Option[Long] = None, order: Long, val title: String)
class Books(tag: Tag) extends Table[Book](tag, "books")
{
def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
def order = column[Long]("order")
def title = column[String]("title")
def * = (id, order, title) <> (Book.tupled, Book.unapply)
def uniqueOrder = index("order", order, unique = true)
def chapters: Query[Chapters, Chapter, Seq] = Chapters.all.filter(_.bookID === id)
}
object Books
{
lazy val all = TableQuery[Books]
val findById = Compiled {id: Rep[Long] => all.filter(_.id === id)}
def add(order: Long, title: String) = all += new Book(None, order, title)
def delete(id: Long) = all.filter(_.id === id).delete
// def withChapters(q: Query[Books, Book, Seq]) = q.join(Chapters.all).on(_.id === _.bookID)
val withChapters = for
{
(Books, Chapters) <- all join Chapters.all on (_.id === _.bookID)
} yield(Books, Chapters)
}
case class Chapter(id: Option[Long] = None, bookID: Long, order: Long, val title: String)
class Chapters(tag: Tag) extends Table[Chapter](tag, "chapters")
{
def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
def bookID = column[Long]("book_id")
def order = column[Long]("order")
def title = column[String]("title")
def * = (id, bookID, order, title) <> (Chapter.tupled, Chapter.unapply)
def uniqueOrder = index("order", order, unique = true)
def bookFK = foreignKey("book_fk", bookID, Books.all)(_.id.get, onUpdate = ForeignKeyAction.Cascade, onDelete = ForeignKeyAction.Restrict)
}
object Chapters
{
lazy val all = TableQuery[Chapters]
val findById = Compiled {id: Rep[Long] => all.filter(_.id === id)}
def add(bookId: Long, order: Long, title: String) = all += new Chapter(None, bookId, order, title)
def delete(id: Long) = all.filter(_.id === id).delete
}
Now what I want to do:
I want to query all or a specific book (by id) with all their chapters
Translated to plain SQL, something like:
SELECT * FROM books b JOIN chapters c ON books.id == c.book_id WHERE books.id = 10
but in Slick I can't really get this whole thing to work.
What I tried:
object Books
{
//...
def withChapters(q: Query[Books, Book, Seq]) = q.join(Chapters.all).on(_.id === _.bookID)
}
as well as:
object Books
{
//...
val withChapters = for
{
(Books, Chapters) <- all join Chapters.all on (_.id === _.bookID)
} yield(Books, Chapters)
}
but to no avail. (I use ScalaTest and I get an empty result (for def withChapters(...)) or another exception for the val withChapters = for...)
How to go on about this? I tried to keep to the documentation, but I'm doing something wrong obviously.
Also: Is there an easy way to see the actual query as a String? I only found query.selectStatement and the like, but that's not available for my joined query. Would be great for debugging to see if the actual query was wrong.
edit: My test looks like this:
class BookWithChapters extends FlatSpec with Matchers with ScalaFutures with BeforeAndAfter
{
val db = Database.forConfig("db.test.h2")
private val books = Books.all
private val chapters = Chapters.all
before { db.run(setup) }
after {db.run(tearDown)}
val setup = DBIO.seq(
(books.schema).create,
(chapters.schema).create
)
val tearDown = DBIO.seq(
(books.schema).drop,
(chapters.schema).drop
)
"Books" should "consist of chapters" in
{
db.run(
DBIO.seq
(
Books.add(0, "Book #1"),
Chapters.add(0, 0, "Chapter #1")
)
)
//whenReady(db.run(Books.withChapters(books).result)) {
whenReady(db.run(Books.withChapters(1).result)) {
result => {
// result should have length 1
print(result(0)._1)
}
}
}
}
like this I get an IndexOutOfBoundsException.
I used this as my method:
object Books
{
def withChapters(id: Long) = Books.all.filter(_.id === id) join Chapters.all on (_.id === _.bookID)
}
also:
logback.xml looks like this:
<configuration>
<logger name="slick.jdbc.JdbcBackend.statement" level="DEBUG/>
</configuration>
Where can I see the logs? Or what else do I have to do to see them?
To translate your query...
SELECT * FROM books b JOIN chapters c ON books.id == c.book_id WHERE books.id = 10
...to Slick we can filter the books:
val bookTenChapters =
Books.all.filter(_.id === 10L) join Chapters.all on (_.id === _.bookID)
This will give you a query that returns Seq[(Books, Chapters)]. If you want to select different books, you can use a different filter expression.
Alternatively, you may prefer to filter on the join:
val everything =
Books.all join Chapters.all on (_.id === _.bookID)
val bookTenChapters =
everything.filter { case (book, chapter) => book.id === 10L }
That will probably be closer to your join. Check the SQL generated with the database you use to see which you prefer.
You can log the query by creating a src/main/resources/logback.xml file and set:
<logger name="slick.jdbc.JdbcBackend.statement" level="DEBUG"/>
I have an example project with logging set up. You will need to change INFO to DEBUG in the xml file in, e.g., the chapter-01 folder.

How to return a Bool from a Where Filter using Entity Framework and Esql

I use c# and ef4.
I have a Model with an Entity with two proprieties int Id and string Title.
I need to write an ESQL query that is able to return bool TRUE if Id and Title are present in the DataSource. Please note Id is a PrimaryKey in my data storage.
Any idea how to do it?
You can do it by each code-snippets below:
1)
using (YourEntityContext context = new YourEntityContext ()) {
var queryString =
#"SELECT VALUE TOP(1) Model FROM YourEntityContext.Models
As Model WHERE Model.Id = #id AND Model.Title = #title";
ObjectQuery<Model> entityQuery = new ObjectQuery<Model>(queryString, context);
entityQuery.Parameters.Add(new ObjectParameter("id", id));
entityQuery.Parameters.Add(new ObjectParameter("title", title));
var result = entityQuery.Any();
}
2)
using (YourEntityContext context = new YourEntityContext ()) {
ObjectQuery<Model> entityQuery =
context.Models
.Where("it.Id = #id AND it.Title = #title"
, new ObjectParameter("id", id)
, new ObjectParameter("title", title)
);
var result = entityQuery.Any();
}
3)
var context = new YourEntityContext();
using (EntityConnection cn = context.Connection as EntityConnection) {
if (cn.State == System.Data.ConnectionState.Closed)
cn.Open();
using (EntityCommand cmd = new EntityCommand()) {
cmd.Connection = cn;
cmd.CommandText = #"EXISTS(
SELECT M FROM YourEntityContext.Models as M
WHERE M.Id == #id AND Model.Title = #title
)";
cmd.Parameters.AddWithValue("id", _yourId);
cmd.Parameters.AddWithValue("title", _yourTitle);
var r = (bool)cmd.ExecuteScalar();
}
}
4)
using (YourEntityContext context = new YourEntityContext ()) {
var queryString =
#"EXISTS(
SELECT M FROM YourEntityContext.Models as M
WHERE M.Id == #id AND Model.Title = #title
)";
ObjectQuery<bool> entityQuery = new ObjectQuery<bool>(queryString, context);
entityQuery.Parameters.Add(new ObjectParameter("id", id));
entityQuery.Parameters.Add(new ObjectParameter("title", title));
var result = entityQuery.Execute(MergeOption.AppendOnly).FirstOrDefault();
}
4 is the best way I suggest you. Good lock
What javad said is true, but another way is:
bool result = entities.Any(x=>x.Id == id && x.Title == title) ;
In fact because Id is primary key, DB prevent from occurrence of this more than one time .

Resources